diff --git a/.github/workflows/validations.yaml b/.github/workflows/validations.yaml index 778008799..bf105fc8a 100644 --- a/.github/workflows/validations.yaml +++ b/.github/workflows/validations.yaml @@ -86,8 +86,8 @@ jobs: - name: Restore integration test cache uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 #v4.0.0 with: - path: ${{ github.workspace }}/test/integration/test-fixtures/cache - key: ${{ runner.os }}-integration-test-cache-${{ hashFiles('test/integration/test-fixtures/cache.fingerprint') }} + path: ${{ github.workspace }}/cmd/syft/internal/test/integration/test-fixtures/cache + key: ${{ runner.os }}-integration-test-cache-${{ hashFiles('/cmd/syft/internal/test/integration/test-fixtures/cache.fingerprint') }} - name: Run integration tests run: make integration diff --git a/.gitignore b/.gitignore index d80e8f4ff..3ba60dc50 100644 --- a/.gitignore +++ b/.gitignore @@ -32,7 +32,6 @@ VERSION /test/results coverage.txt *.log -test/integration/test-fixtures/**/go.sum # probable archives .images diff --git a/DEVELOPING.md b/DEVELOPING.md index 7d5db769a..2308c51b1 100644 --- a/DEVELOPING.md +++ b/DEVELOPING.md @@ -234,7 +234,7 @@ rough outline how that works: the `/test` directory. These tests should focus on correctness of functionality in depth. % test coverage metrics only considers unit tests and no other forms of testing. -- `integration`: located within `test/integration`, these tests focus on the behavior surfaced by the common library +- `integration`: located within `cmd/syft/internal/test/integration`, these tests focus on the behavior surfaced by the common library entrypoints from the `syft` package and make light assertions about the results surfaced. Additionally, these tests tend to make diversity assertions for enum-like objects, ensuring that as enum values are added to a definition that integration tests will automatically fail if no test attempts to use that enum value. For more details see diff --git a/Taskfile.yaml b/Taskfile.yaml index e6f9115c7..f5487bf9f 100644 --- a/Taskfile.yaml +++ b/Taskfile.yaml @@ -185,7 +185,7 @@ tasks: - fixtures vars: TEST_PKGS: - sh: "go list ./... | grep -v {{ .OWNER }}/{{ .PROJECT }}/test | tr '\n' ' '" + sh: "go list ./... | grep -v {{ .OWNER }}/{{ .PROJECT }}/test | grep -v {{ .OWNER }}/{{ .PROJECT }}/cmd/syft/internal/test | tr '\n' ' '" # unit test coverage threshold (in % coverage) COVERAGE_THRESHOLD: 62 @@ -197,7 +197,7 @@ tasks: integration: desc: Run integration tests cmds: - - "go test -v ./test/integration" + - "go test -v ./cmd/syft/internal/test/integration" # exercise most of the CLI with the data race detector - "go run -race cmd/syft/main.go alpine:latest" @@ -265,7 +265,7 @@ tasks: fingerprints: desc: Generate test fixture fingerprints generates: - - test/integration/test-fixtures/cache.fingerprint + - cmd/syft/internal/test/integration/test-fixtures/cache.fingerprint - syft/pkg/cataloger/binary/test-fixtures/cache.fingerprint - syft/pkg/cataloger/java/test-fixtures/java-builds/cache.fingerprint - syft/pkg/cataloger/golang/test-fixtures/archs/binaries.fingerprint @@ -275,7 +275,7 @@ tasks: - test/cli/test-fixtures/cache.fingerprint cmds: # for IMAGE integration test fixtures - - "cd test/integration/test-fixtures && make cache.fingerprint" + - "cd cmd/syft/internal/test/integration/test-fixtures && make cache.fingerprint" # for BINARY test fixtures - "cd syft/pkg/cataloger/binary/test-fixtures && make cache.fingerprint" # for JAVA BUILD test fixtures @@ -286,7 +286,7 @@ tasks: - "cd syft/pkg/cataloger/redhat/test-fixtures && make rpms.fingerprint" # for Kernel test fixtures - "cd syft/pkg/cataloger/kernel/test-fixtures && make cache.fingerprint" - # for INSTALL integration test fixtures + # for INSTALL test fixtures - "cd test/install && make cache.fingerprint" # for CLI test fixtures - "cd test/cli/test-fixtures && make cache.fingerprint" diff --git a/cmd/syft/cli/cli.go b/cmd/syft/cli/cli.go index 179533ce4..534e90ef6 100644 --- a/cmd/syft/cli/cli.go +++ b/cmd/syft/cli/cli.go @@ -9,8 +9,8 @@ import ( "github.com/anchore/clio" "github.com/anchore/stereoscope" - "github.com/anchore/syft/cmd/syft/cli/commands" handler "github.com/anchore/syft/cmd/syft/cli/ui" + "github.com/anchore/syft/cmd/syft/internal/commands" "github.com/anchore/syft/cmd/syft/internal/ui" "github.com/anchore/syft/internal/bus" "github.com/anchore/syft/internal/log" diff --git a/cmd/syft/cli/options/format.go b/cmd/syft/cli/options/format.go deleted file mode 100644 index 03d9bf423..000000000 --- a/cmd/syft/cli/options/format.go +++ /dev/null @@ -1,129 +0,0 @@ -package options - -import ( - "fmt" - - "github.com/hashicorp/go-multierror" - - "github.com/anchore/clio" - "github.com/anchore/syft/syft/format/cyclonedxjson" - "github.com/anchore/syft/syft/format/cyclonedxxml" - "github.com/anchore/syft/syft/format/github" - "github.com/anchore/syft/syft/format/spdxjson" - "github.com/anchore/syft/syft/format/spdxtagvalue" - "github.com/anchore/syft/syft/format/syftjson" - "github.com/anchore/syft/syft/format/table" - "github.com/anchore/syft/syft/format/template" - "github.com/anchore/syft/syft/format/text" - "github.com/anchore/syft/syft/sbom" -) - -var _ clio.PostLoader = (*Format)(nil) - -// Format contains all user configuration for output formatting. -type Format struct { - Pretty *bool `yaml:"pretty" json:"pretty" mapstructure:"pretty"` - Template FormatTemplate `yaml:"template" json:"template" mapstructure:"template"` - SyftJSON FormatSyftJSON `yaml:"json" json:"json" mapstructure:"json"` - SPDXJSON FormatSPDXJSON `yaml:"spdx-json" json:"spdx-json" mapstructure:"spdx-json"` - CyclonedxJSON FormatCyclonedxJSON `yaml:"cyclonedx-json" json:"cyclonedx-json" mapstructure:"cyclonedx-json"` - CyclonedxXML FormatCyclonedxXML `yaml:"cyclonedx-xml" json:"cyclonedx-xml" mapstructure:"cyclonedx-xml"` -} - -func (o *Format) PostLoad() error { - o.SyftJSON.Pretty = multiLevelOption[bool](false, o.Pretty, o.SyftJSON.Pretty) - o.SPDXJSON.Pretty = multiLevelOption[bool](false, o.Pretty, o.SPDXJSON.Pretty) - o.CyclonedxJSON.Pretty = multiLevelOption[bool](false, o.Pretty, o.CyclonedxJSON.Pretty) - o.CyclonedxXML.Pretty = multiLevelOption[bool](false, o.Pretty, o.CyclonedxXML.Pretty) - - return nil -} - -func DefaultFormat() Format { - return Format{ - Template: DefaultFormatTemplate(), - SyftJSON: DefaultFormatJSON(), - SPDXJSON: DefaultFormatSPDXJSON(), - CyclonedxJSON: DefaultFormatCyclonedxJSON(), - CyclonedxXML: DefaultFormatCyclonedxXML(), - } -} - -func (o *Format) Encoders() ([]sbom.FormatEncoder, error) { - // setup all encoders based on the configuration - var list encoderList - - // in the future there will be application configuration options that can be used to set the default output format - list.addWithErr(template.ID)(o.Template.formatEncoders()) - list.addWithErr(syftjson.ID)(o.SyftJSON.formatEncoders()) - list.add(table.ID)(table.NewFormatEncoder()) - list.add(text.ID)(text.NewFormatEncoder()) - list.add(github.ID)(github.NewFormatEncoder()) - list.addWithErr(cyclonedxxml.ID)(o.CyclonedxXML.formatEncoders()) - list.addWithErr(cyclonedxjson.ID)(o.CyclonedxJSON.formatEncoders()) - list.addWithErr(spdxjson.ID)(o.SPDXJSON.formatEncoders()) - list.addWithErr(spdxtagvalue.ID)(spdxTagValueEncoders()) - - return list.encoders, list.err -} - -// TODO: when application configuration is made for this format then this should be ported to the options object -// that is created for that configuration (as done with the template output option) -func spdxTagValueEncoders() ([]sbom.FormatEncoder, error) { - var ( - encs []sbom.FormatEncoder - errs error - ) - for _, v := range spdxtagvalue.SupportedVersions() { - enc, err := spdxtagvalue.NewFormatEncoderWithConfig(spdxtagvalue.EncoderConfig{Version: v}) - if err != nil { - errs = multierror.Append(errs, err) - } else { - encs = append(encs, enc) - } - } - return encs, errs -} - -type encoderList struct { - encoders []sbom.FormatEncoder - err error -} - -func (l *encoderList) addWithErr(name sbom.FormatID) func([]sbom.FormatEncoder, error) { - return func(encs []sbom.FormatEncoder, err error) { - if err != nil { - l.err = multierror.Append(l.err, fmt.Errorf("unable to configure %q format encoder: %w", name, err)) - return - } - for _, enc := range encs { - if enc == nil { - l.err = multierror.Append(l.err, fmt.Errorf("unable to configure %q format encoder: nil encoder returned", name)) - continue - } - l.encoders = append(l.encoders, enc) - } - } -} - -func (l *encoderList) add(name sbom.FormatID) func(...sbom.FormatEncoder) { - return func(encs ...sbom.FormatEncoder) { - for _, enc := range encs { - if enc == nil { - l.err = multierror.Append(l.err, fmt.Errorf("unable to configure %q format encoder: nil encoder returned", name)) - continue - } - l.encoders = append(l.encoders, enc) - } - } -} - -func multiLevelOption[T any](defaultValue T, option ...*T) *T { - result := defaultValue - for _, opt := range option { - if opt != nil { - result = *opt - } - } - return &result -} diff --git a/cmd/syft/cli/options/format_cyclonedx_json.go b/cmd/syft/cli/options/format_cyclonedx_json.go deleted file mode 100644 index 8d2fecbba..000000000 --- a/cmd/syft/cli/options/format_cyclonedx_json.go +++ /dev/null @@ -1,43 +0,0 @@ -package options - -import ( - "github.com/hashicorp/go-multierror" - - "github.com/anchore/syft/syft/format/cyclonedxjson" - "github.com/anchore/syft/syft/sbom" -) - -type FormatCyclonedxJSON struct { - Pretty *bool `yaml:"pretty" json:"pretty" mapstructure:"pretty"` -} - -func DefaultFormatCyclonedxJSON() FormatCyclonedxJSON { - return FormatCyclonedxJSON{} -} - -func (o FormatCyclonedxJSON) formatEncoders() ([]sbom.FormatEncoder, error) { - var ( - encs []sbom.FormatEncoder - errs error - ) - for _, v := range cyclonedxjson.SupportedVersions() { - enc, err := cyclonedxjson.NewFormatEncoderWithConfig(o.buildConfig(v)) - if err != nil { - errs = multierror.Append(errs, err) - } else { - encs = append(encs, enc) - } - } - return encs, errs -} - -func (o FormatCyclonedxJSON) buildConfig(version string) cyclonedxjson.EncoderConfig { - var pretty bool - if o.Pretty != nil { - pretty = *o.Pretty - } - return cyclonedxjson.EncoderConfig{ - Version: version, - Pretty: pretty, - } -} diff --git a/cmd/syft/cli/options/format_cyclonedx_xml.go b/cmd/syft/cli/options/format_cyclonedx_xml.go deleted file mode 100644 index 359806db3..000000000 --- a/cmd/syft/cli/options/format_cyclonedx_xml.go +++ /dev/null @@ -1,43 +0,0 @@ -package options - -import ( - "github.com/hashicorp/go-multierror" - - "github.com/anchore/syft/syft/format/cyclonedxxml" - "github.com/anchore/syft/syft/sbom" -) - -type FormatCyclonedxXML struct { - Pretty *bool `yaml:"pretty" json:"pretty" mapstructure:"pretty"` -} - -func DefaultFormatCyclonedxXML() FormatCyclonedxXML { - return FormatCyclonedxXML{} -} - -func (o FormatCyclonedxXML) formatEncoders() ([]sbom.FormatEncoder, error) { - var ( - encs []sbom.FormatEncoder - errs error - ) - for _, v := range cyclonedxxml.SupportedVersions() { - enc, err := cyclonedxxml.NewFormatEncoderWithConfig(o.buildConfig(v)) - if err != nil { - errs = multierror.Append(errs, err) - } else { - encs = append(encs, enc) - } - } - return encs, errs -} - -func (o FormatCyclonedxXML) buildConfig(version string) cyclonedxxml.EncoderConfig { - var pretty bool - if o.Pretty != nil { - pretty = *o.Pretty - } - return cyclonedxxml.EncoderConfig{ - Version: version, - Pretty: pretty, - } -} diff --git a/cmd/syft/cli/options/format_spdx_json.go b/cmd/syft/cli/options/format_spdx_json.go deleted file mode 100644 index 002e996a3..000000000 --- a/cmd/syft/cli/options/format_spdx_json.go +++ /dev/null @@ -1,43 +0,0 @@ -package options - -import ( - "github.com/hashicorp/go-multierror" - - "github.com/anchore/syft/syft/format/spdxjson" - "github.com/anchore/syft/syft/sbom" -) - -type FormatSPDXJSON struct { - Pretty *bool `yaml:"pretty" json:"pretty" mapstructure:"pretty"` -} - -func DefaultFormatSPDXJSON() FormatSPDXJSON { - return FormatSPDXJSON{} -} - -func (o FormatSPDXJSON) formatEncoders() ([]sbom.FormatEncoder, error) { - var ( - encs []sbom.FormatEncoder - errs error - ) - for _, v := range spdxjson.SupportedVersions() { - enc, err := spdxjson.NewFormatEncoderWithConfig(o.buildConfig(v)) - if err != nil { - errs = multierror.Append(errs, err) - } else { - encs = append(encs, enc) - } - } - return encs, errs -} - -func (o FormatSPDXJSON) buildConfig(v string) spdxjson.EncoderConfig { - var pretty bool - if o.Pretty != nil { - pretty = *o.Pretty - } - return spdxjson.EncoderConfig{ - Version: v, - Pretty: pretty, - } -} diff --git a/cmd/syft/cli/commands/attest.go b/cmd/syft/internal/commands/attest.go similarity index 99% rename from cmd/syft/cli/commands/attest.go rename to cmd/syft/internal/commands/attest.go index 71e69b558..0d9bbdc59 100644 --- a/cmd/syft/cli/commands/attest.go +++ b/cmd/syft/internal/commands/attest.go @@ -13,7 +13,7 @@ import ( "github.com/wagoodman/go-progress" "github.com/anchore/clio" - "github.com/anchore/syft/cmd/syft/cli/options" + "github.com/anchore/syft/cmd/syft/internal/options" "github.com/anchore/syft/cmd/syft/internal/ui" "github.com/anchore/syft/internal" "github.com/anchore/syft/internal/bus" diff --git a/cmd/syft/cli/commands/attest_test.go b/cmd/syft/internal/commands/attest_test.go similarity index 99% rename from cmd/syft/cli/commands/attest_test.go rename to cmd/syft/internal/commands/attest_test.go index 6391f6311..c090c861b 100644 --- a/cmd/syft/cli/commands/attest_test.go +++ b/cmd/syft/internal/commands/attest_test.go @@ -14,7 +14,7 @@ import ( "github.com/stretchr/testify/require" "github.com/anchore/clio" - "github.com/anchore/syft/cmd/syft/cli/options" + "github.com/anchore/syft/cmd/syft/internal/options" "github.com/anchore/syft/syft/sbom" "github.com/anchore/syft/syft/source" ) diff --git a/cmd/syft/cli/commands/cataloger.go b/cmd/syft/internal/commands/cataloger.go similarity index 100% rename from cmd/syft/cli/commands/cataloger.go rename to cmd/syft/internal/commands/cataloger.go diff --git a/cmd/syft/cli/commands/cataloger_list.go b/cmd/syft/internal/commands/cataloger_list.go similarity index 100% rename from cmd/syft/cli/commands/cataloger_list.go rename to cmd/syft/internal/commands/cataloger_list.go diff --git a/cmd/syft/cli/commands/cataloger_list_test.go b/cmd/syft/internal/commands/cataloger_list_test.go similarity index 100% rename from cmd/syft/cli/commands/cataloger_list_test.go rename to cmd/syft/internal/commands/cataloger_list_test.go diff --git a/cmd/syft/cli/commands/convert.go b/cmd/syft/internal/commands/convert.go similarity index 98% rename from cmd/syft/cli/commands/convert.go rename to cmd/syft/internal/commands/convert.go index 3a3687811..193fe5a2b 100644 --- a/cmd/syft/cli/commands/convert.go +++ b/cmd/syft/internal/commands/convert.go @@ -8,7 +8,7 @@ import ( "github.com/spf13/cobra" "github.com/anchore/clio" - "github.com/anchore/syft/cmd/syft/cli/options" + "github.com/anchore/syft/cmd/syft/internal/options" "github.com/anchore/syft/cmd/syft/internal/ui" "github.com/anchore/syft/internal" "github.com/anchore/syft/internal/log" diff --git a/cmd/syft/cli/commands/packages.go b/cmd/syft/internal/commands/packages.go similarity index 100% rename from cmd/syft/cli/commands/packages.go rename to cmd/syft/internal/commands/packages.go diff --git a/cmd/syft/cli/commands/packages_test.go b/cmd/syft/internal/commands/packages_test.go similarity index 100% rename from cmd/syft/cli/commands/packages_test.go rename to cmd/syft/internal/commands/packages_test.go diff --git a/cmd/syft/cli/commands/root.go b/cmd/syft/internal/commands/root.go similarity index 100% rename from cmd/syft/cli/commands/root.go rename to cmd/syft/internal/commands/root.go diff --git a/cmd/syft/cli/commands/scan.go b/cmd/syft/internal/commands/scan.go similarity index 99% rename from cmd/syft/cli/commands/scan.go rename to cmd/syft/internal/commands/scan.go index c2fb72f40..c70d84e99 100644 --- a/cmd/syft/cli/commands/scan.go +++ b/cmd/syft/internal/commands/scan.go @@ -14,7 +14,7 @@ import ( "github.com/anchore/clio" "github.com/anchore/stereoscope/pkg/image" - "github.com/anchore/syft/cmd/syft/cli/options" + "github.com/anchore/syft/cmd/syft/internal/options" "github.com/anchore/syft/cmd/syft/internal/ui" "github.com/anchore/syft/internal" "github.com/anchore/syft/internal/bus" diff --git a/cmd/syft/cli/commands/scan_test.go b/cmd/syft/internal/commands/scan_test.go similarity index 97% rename from cmd/syft/cli/commands/scan_test.go rename to cmd/syft/internal/commands/scan_test.go index e2dbc58e8..63f22543f 100644 --- a/cmd/syft/cli/commands/scan_test.go +++ b/cmd/syft/internal/commands/scan_test.go @@ -5,7 +5,7 @@ import ( "github.com/stretchr/testify/assert" - "github.com/anchore/syft/cmd/syft/cli/options" + "github.com/anchore/syft/cmd/syft/internal/options" ) func Test_scanOptions_validateLegacyOptionsNotUsed(t *testing.T) { diff --git a/cmd/syft/cli/commands/test-fixtures/scan-configs/no-legacy-options.yaml b/cmd/syft/internal/commands/test-fixtures/scan-configs/no-legacy-options.yaml similarity index 100% rename from cmd/syft/cli/commands/test-fixtures/scan-configs/no-legacy-options.yaml rename to cmd/syft/internal/commands/test-fixtures/scan-configs/no-legacy-options.yaml diff --git a/cmd/syft/cli/commands/test-fixtures/scan-configs/with-base-path.yaml b/cmd/syft/internal/commands/test-fixtures/scan-configs/with-base-path.yaml similarity index 100% rename from cmd/syft/cli/commands/test-fixtures/scan-configs/with-base-path.yaml rename to cmd/syft/internal/commands/test-fixtures/scan-configs/with-base-path.yaml diff --git a/cmd/syft/cli/commands/test-fixtures/scan-configs/with-default-pull-source.yaml b/cmd/syft/internal/commands/test-fixtures/scan-configs/with-default-pull-source.yaml similarity index 100% rename from cmd/syft/cli/commands/test-fixtures/scan-configs/with-default-pull-source.yaml rename to cmd/syft/internal/commands/test-fixtures/scan-configs/with-default-pull-source.yaml diff --git a/cmd/syft/cli/commands/test-fixtures/scan-configs/with-exclude-binary-overlap-by-ownership.yaml b/cmd/syft/internal/commands/test-fixtures/scan-configs/with-exclude-binary-overlap-by-ownership.yaml similarity index 100% rename from cmd/syft/cli/commands/test-fixtures/scan-configs/with-exclude-binary-overlap-by-ownership.yaml rename to cmd/syft/internal/commands/test-fixtures/scan-configs/with-exclude-binary-overlap-by-ownership.yaml diff --git a/cmd/syft/cli/commands/test-fixtures/scan-configs/with-file-section.yaml b/cmd/syft/internal/commands/test-fixtures/scan-configs/with-file-section.yaml similarity index 100% rename from cmd/syft/cli/commands/test-fixtures/scan-configs/with-file-section.yaml rename to cmd/syft/internal/commands/test-fixtures/scan-configs/with-file-section.yaml diff --git a/cmd/syft/cli/commands/test-fixtures/scan-configs/with-file-string.yaml b/cmd/syft/internal/commands/test-fixtures/scan-configs/with-file-string.yaml similarity index 100% rename from cmd/syft/cli/commands/test-fixtures/scan-configs/with-file-string.yaml rename to cmd/syft/internal/commands/test-fixtures/scan-configs/with-file-string.yaml diff --git a/cmd/syft/cli/commands/update.go b/cmd/syft/internal/commands/update.go similarity index 98% rename from cmd/syft/cli/commands/update.go rename to cmd/syft/internal/commands/update.go index 88f159700..e8edf9947 100644 --- a/cmd/syft/cli/commands/update.go +++ b/cmd/syft/internal/commands/update.go @@ -11,8 +11,8 @@ import ( "github.com/anchore/clio" hashiVersion "github.com/anchore/go-version" - "github.com/anchore/syft/cmd/syft/cli/options" "github.com/anchore/syft/cmd/syft/internal" + "github.com/anchore/syft/cmd/syft/internal/options" "github.com/anchore/syft/internal/bus" "github.com/anchore/syft/internal/log" "github.com/anchore/syft/syft/event" diff --git a/cmd/syft/cli/commands/update_test.go b/cmd/syft/internal/commands/update_test.go similarity index 100% rename from cmd/syft/cli/commands/update_test.go rename to cmd/syft/internal/commands/update_test.go diff --git a/cmd/syft/cli/options/attest.go b/cmd/syft/internal/options/attest.go similarity index 100% rename from cmd/syft/cli/options/attest.go rename to cmd/syft/internal/options/attest.go diff --git a/cmd/syft/cli/options/catalog.go b/cmd/syft/internal/options/catalog.go similarity index 100% rename from cmd/syft/cli/options/catalog.go rename to cmd/syft/internal/options/catalog.go diff --git a/cmd/syft/cli/options/catalog_test.go b/cmd/syft/internal/options/catalog_test.go similarity index 100% rename from cmd/syft/cli/options/catalog_test.go rename to cmd/syft/internal/options/catalog_test.go diff --git a/cmd/syft/cli/options/config.go b/cmd/syft/internal/options/config.go similarity index 100% rename from cmd/syft/cli/options/config.go rename to cmd/syft/internal/options/config.go diff --git a/cmd/syft/cli/options/file.go b/cmd/syft/internal/options/file.go similarity index 100% rename from cmd/syft/cli/options/file.go rename to cmd/syft/internal/options/file.go diff --git a/cmd/syft/cli/options/file_test.go b/cmd/syft/internal/options/file_test.go similarity index 100% rename from cmd/syft/cli/options/file_test.go rename to cmd/syft/internal/options/file_test.go diff --git a/cmd/syft/internal/options/format.go b/cmd/syft/internal/options/format.go new file mode 100644 index 000000000..e5ab65bb4 --- /dev/null +++ b/cmd/syft/internal/options/format.go @@ -0,0 +1,58 @@ +package options + +import ( + "github.com/anchore/clio" + "github.com/anchore/syft/syft/format" + "github.com/anchore/syft/syft/sbom" +) + +var _ clio.PostLoader = (*Format)(nil) + +// Format contains all user configuration for output formatting. +type Format struct { + Pretty *bool `yaml:"pretty" json:"pretty" mapstructure:"pretty"` + Template FormatTemplate `yaml:"template" json:"template" mapstructure:"template"` + SyftJSON FormatSyftJSON `yaml:"json" json:"json" mapstructure:"json"` + SPDXJSON FormatSPDXJSON `yaml:"spdx-json" json:"spdx-json" mapstructure:"spdx-json"` + CyclonedxJSON FormatCyclonedxJSON `yaml:"cyclonedx-json" json:"cyclonedx-json" mapstructure:"cyclonedx-json"` + CyclonedxXML FormatCyclonedxXML `yaml:"cyclonedx-xml" json:"cyclonedx-xml" mapstructure:"cyclonedx-xml"` +} + +func (o *Format) PostLoad() error { + o.SyftJSON.Pretty = multiLevelOption[bool](false, o.Pretty, o.SyftJSON.Pretty) + o.SPDXJSON.Pretty = multiLevelOption[bool](false, o.Pretty, o.SPDXJSON.Pretty) + o.CyclonedxJSON.Pretty = multiLevelOption[bool](false, o.Pretty, o.CyclonedxJSON.Pretty) + o.CyclonedxXML.Pretty = multiLevelOption[bool](false, o.Pretty, o.CyclonedxXML.Pretty) + + return nil +} + +func DefaultFormat() Format { + return Format{ + Template: DefaultFormatTemplate(), + SyftJSON: DefaultFormatJSON(), + SPDXJSON: DefaultFormatSPDXJSON(), + CyclonedxJSON: DefaultFormatCyclonedxJSON(), + CyclonedxXML: DefaultFormatCyclonedxXML(), + } +} + +func (o Format) Encoders() ([]sbom.FormatEncoder, error) { + return format.EncodersConfig{ + Template: o.Template.config(), + SyftJSON: o.SyftJSON.config(), + SPDXJSON: o.SPDXJSON.config(format.AllVersions), // we support multiple versions, not just a single version + CyclonedxJSON: o.CyclonedxJSON.config(format.AllVersions), // we support multiple versions, not just a single version + CyclonedxXML: o.CyclonedxXML.config(format.AllVersions), // we support multiple versions, not just a single version + }.Encoders() +} + +func multiLevelOption[T any](defaultValue T, option ...*T) *T { + result := defaultValue + for _, opt := range option { + if opt != nil { + result = *opt + } + } + return &result +} diff --git a/cmd/syft/internal/options/format_cyclonedx_json.go b/cmd/syft/internal/options/format_cyclonedx_json.go new file mode 100644 index 000000000..eb65264ca --- /dev/null +++ b/cmd/syft/internal/options/format_cyclonedx_json.go @@ -0,0 +1,24 @@ +package options + +import ( + "github.com/anchore/syft/syft/format/cyclonedxjson" +) + +type FormatCyclonedxJSON struct { + Pretty *bool `yaml:"pretty" json:"pretty" mapstructure:"pretty"` +} + +func DefaultFormatCyclonedxJSON() FormatCyclonedxJSON { + return FormatCyclonedxJSON{} +} + +func (o FormatCyclonedxJSON) config(version string) cyclonedxjson.EncoderConfig { + var pretty bool + if o.Pretty != nil { + pretty = *o.Pretty + } + return cyclonedxjson.EncoderConfig{ + Version: version, + Pretty: pretty, + } +} diff --git a/cmd/syft/cli/options/format_cyclonedx_json_test.go b/cmd/syft/internal/options/format_cyclonedx_json_test.go similarity index 97% rename from cmd/syft/cli/options/format_cyclonedx_json_test.go rename to cmd/syft/internal/options/format_cyclonedx_json_test.go index 53b7a6adb..af43574fb 100644 --- a/cmd/syft/cli/options/format_cyclonedx_json_test.go +++ b/cmd/syft/internal/options/format_cyclonedx_json_test.go @@ -13,7 +13,7 @@ func TestFormatCyclonedxJSON_buildConfig(t *testing.T) { ft := &FormatCyclonedxJSON{} ft = setAllToNonZero(t, ft).(*FormatCyclonedxJSON) - subject := ft.buildConfig("Version") + subject := ft.config("Version") assertExpectedValue(t, subject) } diff --git a/cmd/syft/internal/options/format_cyclonedx_xml.go b/cmd/syft/internal/options/format_cyclonedx_xml.go new file mode 100644 index 000000000..3b7577758 --- /dev/null +++ b/cmd/syft/internal/options/format_cyclonedx_xml.go @@ -0,0 +1,24 @@ +package options + +import ( + "github.com/anchore/syft/syft/format/cyclonedxxml" +) + +type FormatCyclonedxXML struct { + Pretty *bool `yaml:"pretty" json:"pretty" mapstructure:"pretty"` +} + +func DefaultFormatCyclonedxXML() FormatCyclonedxXML { + return FormatCyclonedxXML{} +} + +func (o FormatCyclonedxXML) config(version string) cyclonedxxml.EncoderConfig { + var pretty bool + if o.Pretty != nil { + pretty = *o.Pretty + } + return cyclonedxxml.EncoderConfig{ + Version: version, + Pretty: pretty, + } +} diff --git a/cmd/syft/cli/options/format_cyclonedx_xml_test.go b/cmd/syft/internal/options/format_cyclonedx_xml_test.go similarity index 88% rename from cmd/syft/cli/options/format_cyclonedx_xml_test.go rename to cmd/syft/internal/options/format_cyclonedx_xml_test.go index f1b4c656f..31ddcabbb 100644 --- a/cmd/syft/cli/options/format_cyclonedx_xml_test.go +++ b/cmd/syft/internal/options/format_cyclonedx_xml_test.go @@ -10,6 +10,6 @@ func TestFormatCyclonedxXML_buildConfig(t *testing.T) { ft := FormatCyclonedxXML{} ftp := setAllToNonZero(t, &ft).(*FormatCyclonedxXML) - subject := ftp.buildConfig("Version") + subject := ftp.config("Version") assertExpectedValue(t, subject) } diff --git a/cmd/syft/internal/options/format_spdx_json.go b/cmd/syft/internal/options/format_spdx_json.go new file mode 100644 index 000000000..efdccb230 --- /dev/null +++ b/cmd/syft/internal/options/format_spdx_json.go @@ -0,0 +1,24 @@ +package options + +import ( + "github.com/anchore/syft/syft/format/spdxjson" +) + +type FormatSPDXJSON struct { + Pretty *bool `yaml:"pretty" json:"pretty" mapstructure:"pretty"` +} + +func DefaultFormatSPDXJSON() FormatSPDXJSON { + return FormatSPDXJSON{} +} + +func (o FormatSPDXJSON) config(v string) spdxjson.EncoderConfig { + var pretty bool + if o.Pretty != nil { + pretty = *o.Pretty + } + return spdxjson.EncoderConfig{ + Version: v, + Pretty: pretty, + } +} diff --git a/cmd/syft/cli/options/format_spdx_json_test.go b/cmd/syft/internal/options/format_spdx_json_test.go similarity index 87% rename from cmd/syft/cli/options/format_spdx_json_test.go rename to cmd/syft/internal/options/format_spdx_json_test.go index 8cc390d05..b81ef04c7 100644 --- a/cmd/syft/cli/options/format_spdx_json_test.go +++ b/cmd/syft/internal/options/format_spdx_json_test.go @@ -10,6 +10,6 @@ func TestFormatSPDXJSON_buildConfig(t *testing.T) { ft := &FormatSPDXJSON{} ft = setAllToNonZero(t, ft).(*FormatSPDXJSON) - subject := ft.buildConfig("Version") + subject := ft.config("Version") assertExpectedValue(t, subject) } diff --git a/cmd/syft/cli/options/format_syft_json.go b/cmd/syft/internal/options/format_syft_json.go similarity index 62% rename from cmd/syft/cli/options/format_syft_json.go rename to cmd/syft/internal/options/format_syft_json.go index a2765ba87..85cb193dd 100644 --- a/cmd/syft/cli/options/format_syft_json.go +++ b/cmd/syft/internal/options/format_syft_json.go @@ -2,7 +2,6 @@ package options import ( "github.com/anchore/syft/syft/format/syftjson" - "github.com/anchore/syft/syft/sbom" ) type FormatSyftJSON struct { @@ -16,12 +15,7 @@ func DefaultFormatJSON() FormatSyftJSON { } } -func (o FormatSyftJSON) formatEncoders() ([]sbom.FormatEncoder, error) { - enc, err := syftjson.NewFormatEncoderWithConfig(o.buildConfig()) - return []sbom.FormatEncoder{enc}, err -} - -func (o FormatSyftJSON) buildConfig() syftjson.EncoderConfig { +func (o FormatSyftJSON) config() syftjson.EncoderConfig { var pretty bool if o.Pretty != nil { pretty = *o.Pretty diff --git a/cmd/syft/cli/options/format_syft_json_test.go b/cmd/syft/internal/options/format_syft_json_test.go similarity index 90% rename from cmd/syft/cli/options/format_syft_json_test.go rename to cmd/syft/internal/options/format_syft_json_test.go index 94fc1d07d..2df7d43b2 100644 --- a/cmd/syft/cli/options/format_syft_json_test.go +++ b/cmd/syft/internal/options/format_syft_json_test.go @@ -10,6 +10,6 @@ func TestFormatSyftJSON_buildConfig(t *testing.T) { ft := &FormatSyftJSON{} ft = setAllToNonZero(t, ft).(*FormatSyftJSON) - subject := ft.buildConfig() + subject := ft.config() assertExpectedValue(t, subject) } diff --git a/cmd/syft/cli/options/format_template.go b/cmd/syft/internal/options/format_template.go similarity index 71% rename from cmd/syft/cli/options/format_template.go rename to cmd/syft/internal/options/format_template.go index 724e72891..cd994187e 100644 --- a/cmd/syft/cli/options/format_template.go +++ b/cmd/syft/internal/options/format_template.go @@ -3,7 +3,6 @@ package options import ( "github.com/anchore/clio" "github.com/anchore/syft/syft/format/template" - "github.com/anchore/syft/syft/sbom" ) var _ clio.FlagAdder = (*FormatTemplate)(nil) @@ -26,12 +25,8 @@ func (o *FormatTemplate) AddFlags(flags clio.FlagSet) { } } -func (o FormatTemplate) formatEncoders() ([]sbom.FormatEncoder, error) { - if !o.Enabled { - return nil, nil - } - enc, err := template.NewFormatEncoder(template.EncoderConfig{ +func (o FormatTemplate) config() template.EncoderConfig { + return template.EncoderConfig{ TemplatePath: o.Path, - }) - return []sbom.FormatEncoder{enc}, err + } } diff --git a/cmd/syft/cli/options/golang.go b/cmd/syft/internal/options/golang.go similarity index 100% rename from cmd/syft/cli/options/golang.go rename to cmd/syft/internal/options/golang.go diff --git a/cmd/syft/cli/options/java.go b/cmd/syft/internal/options/java.go similarity index 100% rename from cmd/syft/cli/options/java.go rename to cmd/syft/internal/options/java.go diff --git a/cmd/syft/cli/options/javascript.go b/cmd/syft/internal/options/javascript.go similarity index 100% rename from cmd/syft/cli/options/javascript.go rename to cmd/syft/internal/options/javascript.go diff --git a/cmd/syft/cli/options/linux_kernel.go b/cmd/syft/internal/options/linux_kernel.go similarity index 100% rename from cmd/syft/cli/options/linux_kernel.go rename to cmd/syft/internal/options/linux_kernel.go diff --git a/cmd/syft/cli/options/output.go b/cmd/syft/internal/options/output.go similarity index 100% rename from cmd/syft/cli/options/output.go rename to cmd/syft/internal/options/output.go diff --git a/cmd/syft/cli/options/output_file.go b/cmd/syft/internal/options/output_file.go similarity index 100% rename from cmd/syft/cli/options/output_file.go rename to cmd/syft/internal/options/output_file.go diff --git a/cmd/syft/cli/options/output_test.go b/cmd/syft/internal/options/output_test.go similarity index 100% rename from cmd/syft/cli/options/output_test.go rename to cmd/syft/internal/options/output_test.go diff --git a/cmd/syft/cli/options/pkg.go b/cmd/syft/internal/options/pkg.go similarity index 100% rename from cmd/syft/cli/options/pkg.go rename to cmd/syft/internal/options/pkg.go diff --git a/cmd/syft/cli/options/python.go b/cmd/syft/internal/options/python.go similarity index 100% rename from cmd/syft/cli/options/python.go rename to cmd/syft/internal/options/python.go diff --git a/cmd/syft/cli/options/registry.go b/cmd/syft/internal/options/registry.go similarity index 100% rename from cmd/syft/cli/options/registry.go rename to cmd/syft/internal/options/registry.go diff --git a/cmd/syft/cli/options/registry_test.go b/cmd/syft/internal/options/registry_test.go similarity index 100% rename from cmd/syft/cli/options/registry_test.go rename to cmd/syft/internal/options/registry_test.go diff --git a/cmd/syft/cli/options/relationships.go b/cmd/syft/internal/options/relationships.go similarity index 100% rename from cmd/syft/cli/options/relationships.go rename to cmd/syft/internal/options/relationships.go diff --git a/cmd/syft/cli/options/secret.go b/cmd/syft/internal/options/secret.go similarity index 100% rename from cmd/syft/cli/options/secret.go rename to cmd/syft/internal/options/secret.go diff --git a/cmd/syft/cli/options/source.go b/cmd/syft/internal/options/source.go similarity index 100% rename from cmd/syft/cli/options/source.go rename to cmd/syft/internal/options/source.go diff --git a/cmd/syft/cli/options/source_test.go b/cmd/syft/internal/options/source_test.go similarity index 100% rename from cmd/syft/cli/options/source_test.go rename to cmd/syft/internal/options/source_test.go diff --git a/cmd/syft/cli/options/update_check.go b/cmd/syft/internal/options/update_check.go similarity index 100% rename from cmd/syft/cli/options/update_check.go rename to cmd/syft/internal/options/update_check.go diff --git a/cmd/syft/cli/options/writer.go b/cmd/syft/internal/options/writer.go similarity index 100% rename from cmd/syft/cli/options/writer.go rename to cmd/syft/internal/options/writer.go diff --git a/cmd/syft/cli/options/writer_test.go b/cmd/syft/internal/options/writer_test.go similarity index 100% rename from cmd/syft/cli/options/writer_test.go rename to cmd/syft/internal/options/writer_test.go diff --git a/test/integration/all_layers_squashed_comparison_test.go b/cmd/syft/internal/test/integration/all_layers_squashed_comparison_test.go similarity index 100% rename from test/integration/all_layers_squashed_comparison_test.go rename to cmd/syft/internal/test/integration/all_layers_squashed_comparison_test.go diff --git a/test/integration/catalog_packages_cases_test.go b/cmd/syft/internal/test/integration/catalog_packages_cases_test.go similarity index 100% rename from test/integration/catalog_packages_cases_test.go rename to cmd/syft/internal/test/integration/catalog_packages_cases_test.go diff --git a/test/integration/catalog_packages_test.go b/cmd/syft/internal/test/integration/catalog_packages_test.go similarity index 100% rename from test/integration/catalog_packages_test.go rename to cmd/syft/internal/test/integration/catalog_packages_test.go diff --git a/test/integration/distro_test.go b/cmd/syft/internal/test/integration/distro_test.go similarity index 100% rename from test/integration/distro_test.go rename to cmd/syft/internal/test/integration/distro_test.go diff --git a/test/integration/encode_decode_cycle_test.go b/cmd/syft/internal/test/integration/encode_decode_cycle_test.go similarity index 98% rename from test/integration/encode_decode_cycle_test.go rename to cmd/syft/internal/test/integration/encode_decode_cycle_test.go index 905889277..56bd7b772 100644 --- a/test/integration/encode_decode_cycle_test.go +++ b/cmd/syft/internal/test/integration/encode_decode_cycle_test.go @@ -10,7 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/anchore/syft/cmd/syft/cli/options" + "github.com/anchore/syft/cmd/syft/internal/options" "github.com/anchore/syft/syft/format" "github.com/anchore/syft/syft/format/cyclonedxjson" "github.com/anchore/syft/syft/format/cyclonedxxml" diff --git a/test/integration/files_test.go b/cmd/syft/internal/test/integration/files_test.go similarity index 98% rename from test/integration/files_test.go rename to cmd/syft/internal/test/integration/files_test.go index c2e4bc923..6794eed08 100644 --- a/test/integration/files_test.go +++ b/cmd/syft/internal/test/integration/files_test.go @@ -12,7 +12,7 @@ import ( "github.com/anchore/clio" stereoscopeFile "github.com/anchore/stereoscope/pkg/file" - "github.com/anchore/syft/cmd/syft/cli/options" + "github.com/anchore/syft/cmd/syft/internal/options" "github.com/anchore/syft/syft/cataloging/filecataloging" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/file/cataloger/filecontent" diff --git a/test/integration/go_compiler_detection_test.go b/cmd/syft/internal/test/integration/go_compiler_detection_test.go similarity index 100% rename from test/integration/go_compiler_detection_test.go rename to cmd/syft/internal/test/integration/go_compiler_detection_test.go diff --git a/test/integration/java_purl_test.go b/cmd/syft/internal/test/integration/java_purl_test.go similarity index 100% rename from test/integration/java_purl_test.go rename to cmd/syft/internal/test/integration/java_purl_test.go diff --git a/test/integration/license_list_test.go b/cmd/syft/internal/test/integration/license_list_test.go similarity index 100% rename from test/integration/license_list_test.go rename to cmd/syft/internal/test/integration/license_list_test.go diff --git a/test/integration/mariner_distroless_test.go b/cmd/syft/internal/test/integration/mariner_distroless_test.go similarity index 100% rename from test/integration/mariner_distroless_test.go rename to cmd/syft/internal/test/integration/mariner_distroless_test.go diff --git a/test/integration/node_packages_test.go b/cmd/syft/internal/test/integration/node_packages_test.go similarity index 100% rename from test/integration/node_packages_test.go rename to cmd/syft/internal/test/integration/node_packages_test.go diff --git a/test/integration/package_catalogers_represented_test.go b/cmd/syft/internal/test/integration/package_catalogers_represented_test.go similarity index 100% rename from test/integration/package_catalogers_represented_test.go rename to cmd/syft/internal/test/integration/package_catalogers_represented_test.go diff --git a/test/integration/package_deduplication_test.go b/cmd/syft/internal/test/integration/package_deduplication_test.go similarity index 100% rename from test/integration/package_deduplication_test.go rename to cmd/syft/internal/test/integration/package_deduplication_test.go diff --git a/test/integration/package_ownership_relationship_test.go b/cmd/syft/internal/test/integration/package_ownership_relationship_test.go similarity index 100% rename from test/integration/package_ownership_relationship_test.go rename to cmd/syft/internal/test/integration/package_ownership_relationship_test.go diff --git a/test/integration/regression_apk_scanner_buffer_size_test.go b/cmd/syft/internal/test/integration/regression_apk_scanner_buffer_size_test.go similarity index 100% rename from test/integration/regression_apk_scanner_buffer_size_test.go rename to cmd/syft/internal/test/integration/regression_apk_scanner_buffer_size_test.go diff --git a/test/integration/regression_go_bin_scanner_arch_test.go b/cmd/syft/internal/test/integration/regression_go_bin_scanner_arch_test.go similarity index 100% rename from test/integration/regression_go_bin_scanner_arch_test.go rename to cmd/syft/internal/test/integration/regression_go_bin_scanner_arch_test.go diff --git a/test/integration/regression_java_no_main_package_test.go b/cmd/syft/internal/test/integration/regression_java_no_main_package_test.go similarity index 100% rename from test/integration/regression_java_no_main_package_test.go rename to cmd/syft/internal/test/integration/regression_java_no_main_package_test.go diff --git a/test/integration/regression_java_virtualpath_test.go b/cmd/syft/internal/test/integration/regression_java_virtualpath_test.go similarity index 100% rename from test/integration/regression_java_virtualpath_test.go rename to cmd/syft/internal/test/integration/regression_java_virtualpath_test.go diff --git a/test/integration/regression_photon_package_test.go b/cmd/syft/internal/test/integration/regression_photon_package_test.go similarity index 100% rename from test/integration/regression_photon_package_test.go rename to cmd/syft/internal/test/integration/regression_photon_package_test.go diff --git a/test/integration/regression_sbom_duplicate_relationships_test.go b/cmd/syft/internal/test/integration/regression_sbom_duplicate_relationships_test.go similarity index 100% rename from test/integration/regression_sbom_duplicate_relationships_test.go rename to cmd/syft/internal/test/integration/regression_sbom_duplicate_relationships_test.go diff --git a/test/integration/rust_audit_binary_test.go b/cmd/syft/internal/test/integration/rust_audit_binary_test.go similarity index 100% rename from test/integration/rust_audit_binary_test.go rename to cmd/syft/internal/test/integration/rust_audit_binary_test.go diff --git a/test/integration/sbom_cataloger_test.go b/cmd/syft/internal/test/integration/sbom_cataloger_test.go similarity index 100% rename from test/integration/sbom_cataloger_test.go rename to cmd/syft/internal/test/integration/sbom_cataloger_test.go diff --git a/test/integration/sqlite_rpmdb_test.go b/cmd/syft/internal/test/integration/sqlite_rpmdb_test.go similarity index 100% rename from test/integration/sqlite_rpmdb_test.go rename to cmd/syft/internal/test/integration/sqlite_rpmdb_test.go diff --git a/test/integration/test-fixtures/.gitignore b/cmd/syft/internal/test/integration/test-fixtures/.gitignore similarity index 93% rename from test/integration/test-fixtures/.gitignore rename to cmd/syft/internal/test/integration/test-fixtures/.gitignore index 687856021..ea642e713 100644 --- a/test/integration/test-fixtures/.gitignore +++ b/cmd/syft/internal/test/integration/test-fixtures/.gitignore @@ -5,3 +5,6 @@ # functionality), committing it seems like an acceptable exception. !image-pkg-coverage/pkgs/java/*.jar !image-pkg-coverage/pkgs/java/*.hpi + +**/go.sum +!image-go-bin-arch-coverage/go.sum \ No newline at end of file diff --git a/test/integration/test-fixtures/Makefile b/cmd/syft/internal/test/integration/test-fixtures/Makefile similarity index 100% rename from test/integration/test-fixtures/Makefile rename to cmd/syft/internal/test/integration/test-fixtures/Makefile diff --git a/test/integration/test-fixtures/files/somewhere/there/is/a-small-file b/cmd/syft/internal/test/integration/test-fixtures/files/somewhere/there/is/a-small-file similarity index 100% rename from test/integration/test-fixtures/files/somewhere/there/is/a-small-file rename to cmd/syft/internal/test/integration/test-fixtures/files/somewhere/there/is/a-small-file diff --git a/test/integration/test-fixtures/files/somewhere/there/is/a-symlink-to-a-small-file b/cmd/syft/internal/test/integration/test-fixtures/files/somewhere/there/is/a-symlink-to-a-small-file similarity index 100% rename from test/integration/test-fixtures/files/somewhere/there/is/a-symlink-to-a-small-file rename to cmd/syft/internal/test/integration/test-fixtures/files/somewhere/there/is/a-symlink-to-a-small-file diff --git a/test/integration/test-fixtures/files/somewhere/there/is/a-symlink-to-file b/cmd/syft/internal/test/integration/test-fixtures/files/somewhere/there/is/a-symlink-to-file similarity index 100% rename from test/integration/test-fixtures/files/somewhere/there/is/a-symlink-to-file rename to cmd/syft/internal/test/integration/test-fixtures/files/somewhere/there/is/a-symlink-to-file diff --git a/test/integration/test-fixtures/files/somewhere/there/is/a/file b/cmd/syft/internal/test/integration/test-fixtures/files/somewhere/there/is/a/file similarity index 100% rename from test/integration/test-fixtures/files/somewhere/there/is/a/file rename to cmd/syft/internal/test/integration/test-fixtures/files/somewhere/there/is/a/file diff --git a/test/integration/test-fixtures/image-distro-id/Dockerfile b/cmd/syft/internal/test/integration/test-fixtures/image-distro-id/Dockerfile similarity index 100% rename from test/integration/test-fixtures/image-distro-id/Dockerfile rename to cmd/syft/internal/test/integration/test-fixtures/image-distro-id/Dockerfile diff --git a/test/integration/test-fixtures/image-go-bin-arch-coverage/Dockerfile b/cmd/syft/internal/test/integration/test-fixtures/image-go-bin-arch-coverage/Dockerfile similarity index 100% rename from test/integration/test-fixtures/image-go-bin-arch-coverage/Dockerfile rename to cmd/syft/internal/test/integration/test-fixtures/image-go-bin-arch-coverage/Dockerfile diff --git a/test/integration/test-fixtures/image-go-bin-arch-coverage/app.go b/cmd/syft/internal/test/integration/test-fixtures/image-go-bin-arch-coverage/app.go similarity index 100% rename from test/integration/test-fixtures/image-go-bin-arch-coverage/app.go rename to cmd/syft/internal/test/integration/test-fixtures/image-go-bin-arch-coverage/app.go diff --git a/test/integration/test-fixtures/image-go-bin-arch-coverage/go.mod b/cmd/syft/internal/test/integration/test-fixtures/image-go-bin-arch-coverage/go.mod similarity index 100% rename from test/integration/test-fixtures/image-go-bin-arch-coverage/go.mod rename to cmd/syft/internal/test/integration/test-fixtures/image-go-bin-arch-coverage/go.mod diff --git a/test/integration/test-fixtures/image-go-bin-arch-coverage/go.sum b/cmd/syft/internal/test/integration/test-fixtures/image-go-bin-arch-coverage/go.sum similarity index 100% rename from test/integration/test-fixtures/image-go-bin-arch-coverage/go.sum rename to cmd/syft/internal/test/integration/test-fixtures/image-go-bin-arch-coverage/go.sum diff --git a/test/integration/test-fixtures/image-go-bin-arch-coverage/test b/cmd/syft/internal/test/integration/test-fixtures/image-go-bin-arch-coverage/test similarity index 100% rename from test/integration/test-fixtures/image-go-bin-arch-coverage/test rename to cmd/syft/internal/test/integration/test-fixtures/image-go-bin-arch-coverage/test diff --git a/test/integration/test-fixtures/image-golang-compiler/Dockerfile b/cmd/syft/internal/test/integration/test-fixtures/image-golang-compiler/Dockerfile similarity index 100% rename from test/integration/test-fixtures/image-golang-compiler/Dockerfile rename to cmd/syft/internal/test/integration/test-fixtures/image-golang-compiler/Dockerfile diff --git a/test/integration/test-fixtures/image-java-no-main-package/Dockerfile b/cmd/syft/internal/test/integration/test-fixtures/image-java-no-main-package/Dockerfile similarity index 100% rename from test/integration/test-fixtures/image-java-no-main-package/Dockerfile rename to cmd/syft/internal/test/integration/test-fixtures/image-java-no-main-package/Dockerfile diff --git a/test/integration/test-fixtures/image-java-virtualpath-regression/Dockerfile b/cmd/syft/internal/test/integration/test-fixtures/image-java-virtualpath-regression/Dockerfile similarity index 100% rename from test/integration/test-fixtures/image-java-virtualpath-regression/Dockerfile rename to cmd/syft/internal/test/integration/test-fixtures/image-java-virtualpath-regression/Dockerfile diff --git a/test/integration/test-fixtures/image-large-apk-data/Dockerfile b/cmd/syft/internal/test/integration/test-fixtures/image-large-apk-data/Dockerfile similarity index 100% rename from test/integration/test-fixtures/image-large-apk-data/Dockerfile rename to cmd/syft/internal/test/integration/test-fixtures/image-large-apk-data/Dockerfile diff --git a/test/integration/test-fixtures/image-mariner-distroless/Dockerfile b/cmd/syft/internal/test/integration/test-fixtures/image-mariner-distroless/Dockerfile similarity index 100% rename from test/integration/test-fixtures/image-mariner-distroless/Dockerfile rename to cmd/syft/internal/test/integration/test-fixtures/image-mariner-distroless/Dockerfile diff --git a/test/integration/test-fixtures/image-os-binary-overlap/Dockerfile b/cmd/syft/internal/test/integration/test-fixtures/image-os-binary-overlap/Dockerfile similarity index 100% rename from test/integration/test-fixtures/image-os-binary-overlap/Dockerfile rename to cmd/syft/internal/test/integration/test-fixtures/image-os-binary-overlap/Dockerfile diff --git a/test/integration/test-fixtures/image-owning-package/Dockerfile b/cmd/syft/internal/test/integration/test-fixtures/image-owning-package/Dockerfile similarity index 100% rename from test/integration/test-fixtures/image-owning-package/Dockerfile rename to cmd/syft/internal/test/integration/test-fixtures/image-owning-package/Dockerfile diff --git a/test/integration/test-fixtures/image-photon-all-layers/Dockerfile b/cmd/syft/internal/test/integration/test-fixtures/image-photon-all-layers/Dockerfile similarity index 100% rename from test/integration/test-fixtures/image-photon-all-layers/Dockerfile rename to cmd/syft/internal/test/integration/test-fixtures/image-photon-all-layers/Dockerfile diff --git a/test/integration/test-fixtures/image-pkg-coverage/Dockerfile b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/Dockerfile similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/Dockerfile rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/Dockerfile diff --git a/test/integration/test-fixtures/image-pkg-coverage/cocoapods/Podfile.lock b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/cocoapods/Podfile.lock similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/cocoapods/Podfile.lock rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/cocoapods/Podfile.lock diff --git a/test/integration/test-fixtures/image-pkg-coverage/composer/composer.lock b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/composer/composer.lock similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/composer/composer.lock rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/composer/composer.lock diff --git a/test/integration/test-fixtures/image-pkg-coverage/conan/conanfile.txt b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/conan/conanfile.txt similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/conan/conanfile.txt rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/conan/conanfile.txt diff --git a/test/integration/test-fixtures/image-pkg-coverage/etc/os-release b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/etc/os-release similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/etc/os-release rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/etc/os-release diff --git a/test/integration/test-fixtures/image-pkg-coverage/hackage/cabal.project.freeze b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/hackage/cabal.project.freeze similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/hackage/cabal.project.freeze rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/hackage/cabal.project.freeze diff --git a/test/integration/test-fixtures/image-pkg-coverage/hackage/stack.yaml b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/hackage/stack.yaml similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/hackage/stack.yaml rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/hackage/stack.yaml diff --git a/test/integration/test-fixtures/image-pkg-coverage/hackage/stack.yaml.lock b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/hackage/stack.yaml.lock similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/hackage/stack.yaml.lock rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/hackage/stack.yaml.lock diff --git a/test/integration/test-fixtures/image-pkg-coverage/lib/apk/db/installed b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/lib/apk/db/installed similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/lib/apk/db/installed rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/lib/apk/db/installed diff --git a/test/integration/test-fixtures/image-pkg-coverage/pkgs/dart/pubspec.lock b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/dart/pubspec.lock similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/pkgs/dart/pubspec.lock rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/dart/pubspec.lock diff --git a/test/integration/test-fixtures/image-pkg-coverage/pkgs/dotnet/TestLibrary.deps.json b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/dotnet/TestLibrary.deps.json similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/pkgs/dotnet/TestLibrary.deps.json rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/dotnet/TestLibrary.deps.json diff --git a/test/integration/test-fixtures/image-pkg-coverage/pkgs/elixir/mix.lock b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/elixir/mix.lock similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/pkgs/elixir/mix.lock rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/elixir/mix.lock diff --git a/test/integration/test-fixtures/image-pkg-coverage/pkgs/erlang/rebar.lock b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/erlang/rebar.lock similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/pkgs/erlang/rebar.lock rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/erlang/rebar.lock diff --git a/test/integration/test-fixtures/image-pkg-coverage/pkgs/github-actions/.github/workflows/validations.yaml b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/github-actions/.github/workflows/validations.yaml similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/pkgs/github-actions/.github/workflows/validations.yaml rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/github-actions/.github/workflows/validations.yaml diff --git a/test/integration/test-fixtures/image-pkg-coverage/pkgs/go/go.mod b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/go/go.mod similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/pkgs/go/go.mod rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/go/go.mod diff --git a/test/integration/test-fixtures/image-pkg-coverage/pkgs/java/example-java-app-maven-0.1.0.jar b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/java/example-java-app-maven-0.1.0.jar similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/pkgs/java/example-java-app-maven-0.1.0.jar rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/java/example-java-app-maven-0.1.0.jar diff --git a/test/integration/test-fixtures/image-pkg-coverage/pkgs/java/example-jenkins-plugin.hpi b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/java/example-jenkins-plugin.hpi similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/pkgs/java/example-jenkins-plugin.hpi rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/java/example-jenkins-plugin.hpi diff --git a/test/integration/test-fixtures/image-pkg-coverage/pkgs/java/generate-fixtures.md b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/java/generate-fixtures.md similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/pkgs/java/generate-fixtures.md rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/java/generate-fixtures.md diff --git a/test/integration/test-fixtures/image-pkg-coverage/pkgs/java/pom.xml b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/java/pom.xml similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/pkgs/java/pom.xml rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/java/pom.xml diff --git a/test/integration/test-fixtures/image-pkg-coverage/pkgs/javascript/package-json/package.json b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/javascript/package-json/package.json similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/pkgs/javascript/package-json/package.json rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/javascript/package-json/package.json diff --git a/test/integration/test-fixtures/image-pkg-coverage/pkgs/javascript/package-lock/package-lock.json b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/javascript/package-lock/package-lock.json similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/pkgs/javascript/package-lock/package-lock.json rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/javascript/package-lock/package-lock.json diff --git a/test/integration/test-fixtures/image-pkg-coverage/pkgs/javascript/yarn/yarn.lock b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/javascript/yarn/yarn.lock similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/pkgs/javascript/yarn/yarn.lock rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/javascript/yarn/yarn.lock diff --git a/test/integration/test-fixtures/image-pkg-coverage/pkgs/lib/apk/db/installed b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/lib/apk/db/installed similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/pkgs/lib/apk/db/installed rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/lib/apk/db/installed diff --git a/test/integration/test-fixtures/image-pkg-coverage/pkgs/nix/store/h0cnbmfcn93xm5dg2x27ixhag1cwndga-glibc-2.34-210-bin/share/man/glibc.1 b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/nix/store/h0cnbmfcn93xm5dg2x27ixhag1cwndga-glibc-2.34-210-bin/share/man/glibc.1 similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/pkgs/nix/store/h0cnbmfcn93xm5dg2x27ixhag1cwndga-glibc-2.34-210-bin/share/man/glibc.1 rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/nix/store/h0cnbmfcn93xm5dg2x27ixhag1cwndga-glibc-2.34-210-bin/share/man/glibc.1 diff --git a/test/integration/test-fixtures/image-pkg-coverage/pkgs/php/vendor/composer/installed.json b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/php/vendor/composer/installed.json similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/pkgs/php/vendor/composer/installed.json rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/php/vendor/composer/installed.json diff --git a/test/integration/test-fixtures/image-pkg-coverage/pkgs/python/dist-info/METADATA b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/python/dist-info/METADATA similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/pkgs/python/dist-info/METADATA rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/python/dist-info/METADATA diff --git a/test/integration/test-fixtures/image-pkg-coverage/pkgs/python/dist-info/RECORD b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/python/dist-info/RECORD similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/pkgs/python/dist-info/RECORD rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/python/dist-info/RECORD diff --git a/test/integration/test-fixtures/image-pkg-coverage/pkgs/python/dist-info/top_level.txt b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/python/dist-info/top_level.txt similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/pkgs/python/dist-info/top_level.txt rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/python/dist-info/top_level.txt diff --git a/test/integration/test-fixtures/image-pkg-coverage/pkgs/python/egg-info/PKG-INFO b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/python/egg-info/PKG-INFO similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/pkgs/python/egg-info/PKG-INFO rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/python/egg-info/PKG-INFO diff --git a/test/integration/test-fixtures/image-pkg-coverage/pkgs/python/egg-info/top_level.txt b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/python/egg-info/top_level.txt similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/pkgs/python/egg-info/top_level.txt rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/python/egg-info/top_level.txt diff --git a/test/integration/test-fixtures/image-pkg-coverage/pkgs/python/requires/requirements-dev.txt b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/python/requires/requirements-dev.txt similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/pkgs/python/requires/requirements-dev.txt rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/python/requires/requirements-dev.txt diff --git a/test/integration/test-fixtures/image-pkg-coverage/pkgs/python/requires/requirements.txt b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/python/requires/requirements.txt similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/pkgs/python/requires/requirements.txt rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/python/requires/requirements.txt diff --git a/test/integration/test-fixtures/image-pkg-coverage/pkgs/python/requires/test-requirements.txt b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/python/requires/test-requirements.txt similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/pkgs/python/requires/test-requirements.txt rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/python/requires/test-requirements.txt diff --git a/test/integration/test-fixtures/image-pkg-coverage/pkgs/python/setup/setup.py b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/python/setup/setup.py similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/pkgs/python/setup/setup.py rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/python/setup/setup.py diff --git a/test/integration/test-fixtures/image-pkg-coverage/pkgs/python/someotherpkg-3.19.0-py3.8.egg-info/PKG-INFO b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/python/someotherpkg-3.19.0-py3.8.egg-info/PKG-INFO similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/pkgs/python/someotherpkg-3.19.0-py3.8.egg-info/PKG-INFO rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/python/someotherpkg-3.19.0-py3.8.egg-info/PKG-INFO diff --git a/test/integration/test-fixtures/image-pkg-coverage/pkgs/python/someotherpkg-3.19.0-py3.8.egg-info/top_level.txt b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/python/someotherpkg-3.19.0-py3.8.egg-info/top_level.txt similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/pkgs/python/someotherpkg-3.19.0-py3.8.egg-info/top_level.txt rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/python/someotherpkg-3.19.0-py3.8.egg-info/top_level.txt diff --git a/test/integration/test-fixtures/image-pkg-coverage/pkgs/python/somerequests-3.22.0.dist-info/METADATA b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/python/somerequests-3.22.0.dist-info/METADATA similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/pkgs/python/somerequests-3.22.0.dist-info/METADATA rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/python/somerequests-3.22.0.dist-info/METADATA diff --git a/test/integration/test-fixtures/image-pkg-coverage/pkgs/python/somerequests-3.22.0.dist-info/top_level.txt b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/python/somerequests-3.22.0.dist-info/top_level.txt similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/pkgs/python/somerequests-3.22.0.dist-info/top_level.txt rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/python/somerequests-3.22.0.dist-info/top_level.txt diff --git a/test/integration/test-fixtures/image-pkg-coverage/pkgs/r/base/DESCRIPTION b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/r/base/DESCRIPTION similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/pkgs/r/base/DESCRIPTION rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/r/base/DESCRIPTION diff --git a/test/integration/test-fixtures/image-pkg-coverage/pkgs/ruby/Gemfile.lock b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/ruby/Gemfile.lock similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/pkgs/ruby/Gemfile.lock rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/ruby/Gemfile.lock diff --git a/test/integration/test-fixtures/image-pkg-coverage/pkgs/ruby/specifications/bundler.gemspec b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/ruby/specifications/bundler.gemspec similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/pkgs/ruby/specifications/bundler.gemspec rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/ruby/specifications/bundler.gemspec diff --git a/test/integration/test-fixtures/image-pkg-coverage/pkgs/ruby/specifications/default/unbundler.gemspec b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/ruby/specifications/default/unbundler.gemspec similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/pkgs/ruby/specifications/default/unbundler.gemspec rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/ruby/specifications/default/unbundler.gemspec diff --git a/test/integration/test-fixtures/image-pkg-coverage/pkgs/rust/Cargo.lock b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/rust/Cargo.lock similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/pkgs/rust/Cargo.lock rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/rust/Cargo.lock diff --git a/test/integration/test-fixtures/image-pkg-coverage/pkgs/var/db/pkg/app-containers/skopeo-1.5.1/CONTENTS b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/var/db/pkg/app-containers/skopeo-1.5.1/CONTENTS similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/pkgs/var/db/pkg/app-containers/skopeo-1.5.1/CONTENTS rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/var/db/pkg/app-containers/skopeo-1.5.1/CONTENTS diff --git a/test/integration/test-fixtures/image-pkg-coverage/pkgs/var/db/pkg/app-containers/skopeo-1.5.1/LICENSE b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/var/db/pkg/app-containers/skopeo-1.5.1/LICENSE similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/pkgs/var/db/pkg/app-containers/skopeo-1.5.1/LICENSE rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/var/db/pkg/app-containers/skopeo-1.5.1/LICENSE diff --git a/test/integration/test-fixtures/image-pkg-coverage/pkgs/var/db/pkg/app-containers/skopeo-1.5.1/SIZE b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/var/db/pkg/app-containers/skopeo-1.5.1/SIZE similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/pkgs/var/db/pkg/app-containers/skopeo-1.5.1/SIZE rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/var/db/pkg/app-containers/skopeo-1.5.1/SIZE diff --git a/test/integration/test-fixtures/image-pkg-coverage/pkgs/var/lib/dpkg/status b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/var/lib/dpkg/status similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/pkgs/var/lib/dpkg/status rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/var/lib/dpkg/status diff --git a/test/integration/test-fixtures/image-pkg-coverage/pkgs/var/lib/dpkg/status.d/dash b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/var/lib/dpkg/status.d/dash similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/pkgs/var/lib/dpkg/status.d/dash rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/var/lib/dpkg/status.d/dash diff --git a/test/integration/test-fixtures/image-pkg-coverage/pkgs/var/lib/dpkg/status.d/netbase b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/var/lib/dpkg/status.d/netbase similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/pkgs/var/lib/dpkg/status.d/netbase rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/var/lib/dpkg/status.d/netbase diff --git a/test/integration/test-fixtures/image-pkg-coverage/pkgs/var/lib/pacman/local/ALPM_DB_VERSION b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/var/lib/pacman/local/ALPM_DB_VERSION similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/pkgs/var/lib/pacman/local/ALPM_DB_VERSION rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/var/lib/pacman/local/ALPM_DB_VERSION diff --git a/test/integration/test-fixtures/image-pkg-coverage/pkgs/var/lib/pacman/local/pacman-6.0.1-5/desc b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/var/lib/pacman/local/pacman-6.0.1-5/desc similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/pkgs/var/lib/pacman/local/pacman-6.0.1-5/desc rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/var/lib/pacman/local/pacman-6.0.1-5/desc diff --git a/test/integration/test-fixtures/image-pkg-coverage/pkgs/var/lib/pacman/local/pacman-6.0.1-5/files b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/var/lib/pacman/local/pacman-6.0.1-5/files similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/pkgs/var/lib/pacman/local/pacman-6.0.1-5/files rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/var/lib/pacman/local/pacman-6.0.1-5/files diff --git a/test/integration/test-fixtures/image-pkg-coverage/pkgs/var/lib/pacman/local/pacman-6.0.1-5/mtree b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/var/lib/pacman/local/pacman-6.0.1-5/mtree similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/pkgs/var/lib/pacman/local/pacman-6.0.1-5/mtree rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/var/lib/pacman/local/pacman-6.0.1-5/mtree diff --git a/test/integration/test-fixtures/image-pkg-coverage/pkgs/var/lib/rpm/Packages b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/var/lib/rpm/Packages similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/pkgs/var/lib/rpm/Packages rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/var/lib/rpm/Packages diff --git a/test/integration/test-fixtures/image-pkg-coverage/pkgs/var/lib/rpm/generate-fixture.sh b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/var/lib/rpm/generate-fixture.sh similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/pkgs/var/lib/rpm/generate-fixture.sh rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/pkgs/var/lib/rpm/generate-fixture.sh diff --git a/test/integration/test-fixtures/image-pkg-coverage/swift/Package.resolved b/cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/swift/Package.resolved similarity index 100% rename from test/integration/test-fixtures/image-pkg-coverage/swift/Package.resolved rename to cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage/swift/Package.resolved diff --git a/test/integration/test-fixtures/image-rust-auditable/Dockerfile b/cmd/syft/internal/test/integration/test-fixtures/image-rust-auditable/Dockerfile similarity index 100% rename from test/integration/test-fixtures/image-rust-auditable/Dockerfile rename to cmd/syft/internal/test/integration/test-fixtures/image-rust-auditable/Dockerfile diff --git a/test/integration/test-fixtures/image-sbom-cataloger/Dockerfile b/cmd/syft/internal/test/integration/test-fixtures/image-sbom-cataloger/Dockerfile similarity index 100% rename from test/integration/test-fixtures/image-sbom-cataloger/Dockerfile rename to cmd/syft/internal/test/integration/test-fixtures/image-sbom-cataloger/Dockerfile diff --git a/test/integration/test-fixtures/image-sbom-cataloger/go.mod b/cmd/syft/internal/test/integration/test-fixtures/image-sbom-cataloger/go.mod similarity index 100% rename from test/integration/test-fixtures/image-sbom-cataloger/go.mod rename to cmd/syft/internal/test/integration/test-fixtures/image-sbom-cataloger/go.mod diff --git a/test/integration/test-fixtures/image-sbom-cataloger/test.spdx.json b/cmd/syft/internal/test/integration/test-fixtures/image-sbom-cataloger/test.spdx.json similarity index 100% rename from test/integration/test-fixtures/image-sbom-cataloger/test.spdx.json rename to cmd/syft/internal/test/integration/test-fixtures/image-sbom-cataloger/test.spdx.json diff --git a/test/integration/test-fixtures/image-sqlite-rpmdb/Dockerfile b/cmd/syft/internal/test/integration/test-fixtures/image-sqlite-rpmdb/Dockerfile similarity index 100% rename from test/integration/test-fixtures/image-sqlite-rpmdb/Dockerfile rename to cmd/syft/internal/test/integration/test-fixtures/image-sqlite-rpmdb/Dockerfile diff --git a/test/integration/test-fixtures/image-suse-all-layers/Dockerfile b/cmd/syft/internal/test/integration/test-fixtures/image-suse-all-layers/Dockerfile similarity index 100% rename from test/integration/test-fixtures/image-suse-all-layers/Dockerfile rename to cmd/syft/internal/test/integration/test-fixtures/image-suse-all-layers/Dockerfile diff --git a/test/integration/test-fixtures/image-test-java-purls/Dockerfile b/cmd/syft/internal/test/integration/test-fixtures/image-test-java-purls/Dockerfile similarity index 100% rename from test/integration/test-fixtures/image-test-java-purls/Dockerfile rename to cmd/syft/internal/test/integration/test-fixtures/image-test-java-purls/Dockerfile diff --git a/test/integration/test-fixtures/image-vertical-package-dups/Dockerfile b/cmd/syft/internal/test/integration/test-fixtures/image-vertical-package-dups/Dockerfile similarity index 100% rename from test/integration/test-fixtures/image-vertical-package-dups/Dockerfile rename to cmd/syft/internal/test/integration/test-fixtures/image-vertical-package-dups/Dockerfile diff --git a/test/integration/test-fixtures/npm-lock/node_modules/collapse-white-space/index.d.ts b/cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/collapse-white-space/index.d.ts similarity index 100% rename from test/integration/test-fixtures/npm-lock/node_modules/collapse-white-space/index.d.ts rename to cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/collapse-white-space/index.d.ts diff --git a/test/integration/test-fixtures/npm-lock/node_modules/collapse-white-space/index.js b/cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/collapse-white-space/index.js similarity index 100% rename from test/integration/test-fixtures/npm-lock/node_modules/collapse-white-space/index.js rename to cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/collapse-white-space/index.js diff --git a/test/integration/test-fixtures/npm-lock/node_modules/collapse-white-space/license b/cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/collapse-white-space/license similarity index 100% rename from test/integration/test-fixtures/npm-lock/node_modules/collapse-white-space/license rename to cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/collapse-white-space/license diff --git a/test/integration/test-fixtures/npm-lock/node_modules/collapse-white-space/package-lock.json b/cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/collapse-white-space/package-lock.json similarity index 100% rename from test/integration/test-fixtures/npm-lock/node_modules/collapse-white-space/package-lock.json rename to cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/collapse-white-space/package-lock.json diff --git a/test/integration/test-fixtures/npm-lock/node_modules/collapse-white-space/package.json b/cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/collapse-white-space/package.json similarity index 100% rename from test/integration/test-fixtures/npm-lock/node_modules/collapse-white-space/package.json rename to cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/collapse-white-space/package.json diff --git a/test/integration/test-fixtures/npm-lock/node_modules/collapse-white-space/readme.md b/cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/collapse-white-space/readme.md similarity index 100% rename from test/integration/test-fixtures/npm-lock/node_modules/collapse-white-space/readme.md rename to cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/collapse-white-space/readme.md diff --git a/test/integration/test-fixtures/npm-lock/node_modules/end-of-stream/LICENSE b/cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/end-of-stream/LICENSE similarity index 100% rename from test/integration/test-fixtures/npm-lock/node_modules/end-of-stream/LICENSE rename to cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/end-of-stream/LICENSE diff --git a/test/integration/test-fixtures/npm-lock/node_modules/end-of-stream/README.md b/cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/end-of-stream/README.md similarity index 100% rename from test/integration/test-fixtures/npm-lock/node_modules/end-of-stream/README.md rename to cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/end-of-stream/README.md diff --git a/test/integration/test-fixtures/npm-lock/node_modules/end-of-stream/index.js b/cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/end-of-stream/index.js similarity index 100% rename from test/integration/test-fixtures/npm-lock/node_modules/end-of-stream/index.js rename to cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/end-of-stream/index.js diff --git a/test/integration/test-fixtures/npm-lock/node_modules/end-of-stream/package.json b/cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/end-of-stream/package.json similarity index 100% rename from test/integration/test-fixtures/npm-lock/node_modules/end-of-stream/package.json rename to cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/end-of-stream/package.json diff --git a/test/integration/test-fixtures/npm-lock/node_modules/insert-css/LICENSE b/cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/insert-css/LICENSE similarity index 100% rename from test/integration/test-fixtures/npm-lock/node_modules/insert-css/LICENSE rename to cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/insert-css/LICENSE diff --git a/test/integration/test-fixtures/npm-lock/node_modules/insert-css/example.js b/cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/insert-css/example.js similarity index 100% rename from test/integration/test-fixtures/npm-lock/node_modules/insert-css/example.js rename to cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/insert-css/example.js diff --git a/test/integration/test-fixtures/npm-lock/node_modules/insert-css/index.js b/cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/insert-css/index.js similarity index 100% rename from test/integration/test-fixtures/npm-lock/node_modules/insert-css/index.js rename to cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/insert-css/index.js diff --git a/test/integration/test-fixtures/npm-lock/node_modules/insert-css/package.json b/cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/insert-css/package.json similarity index 100% rename from test/integration/test-fixtures/npm-lock/node_modules/insert-css/package.json rename to cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/insert-css/package.json diff --git a/test/integration/test-fixtures/npm-lock/node_modules/insert-css/readme.markdown b/cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/insert-css/readme.markdown similarity index 100% rename from test/integration/test-fixtures/npm-lock/node_modules/insert-css/readme.markdown rename to cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/insert-css/readme.markdown diff --git a/test/integration/test-fixtures/npm-lock/node_modules/insert-css/test.js b/cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/insert-css/test.js similarity index 98% rename from test/integration/test-fixtures/npm-lock/node_modules/insert-css/test.js rename to cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/insert-css/test.js index 8611e2d0c..d97aee957 100644 --- a/test/integration/test-fixtures/npm-lock/node_modules/insert-css/test.js +++ b/cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/insert-css/test.js @@ -1,7 +1,7 @@ var test = require('tape'); test(function (t) { - var insertCss = require('./'); + var insertCss = require('.'); var initialNbStyleTags = nbStyleTags(); // basic usage diff --git a/test/integration/test-fixtures/npm-lock/node_modules/once/LICENSE b/cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/once/LICENSE similarity index 100% rename from test/integration/test-fixtures/npm-lock/node_modules/once/LICENSE rename to cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/once/LICENSE diff --git a/test/integration/test-fixtures/npm-lock/node_modules/once/README.md b/cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/once/README.md similarity index 100% rename from test/integration/test-fixtures/npm-lock/node_modules/once/README.md rename to cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/once/README.md diff --git a/test/integration/test-fixtures/npm-lock/node_modules/once/once.js b/cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/once/once.js similarity index 100% rename from test/integration/test-fixtures/npm-lock/node_modules/once/once.js rename to cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/once/once.js diff --git a/test/integration/test-fixtures/npm-lock/node_modules/once/package.json b/cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/once/package.json similarity index 100% rename from test/integration/test-fixtures/npm-lock/node_modules/once/package.json rename to cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/once/package.json diff --git a/test/integration/test-fixtures/npm-lock/node_modules/pump/.travis.yml b/cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/pump/.travis.yml similarity index 100% rename from test/integration/test-fixtures/npm-lock/node_modules/pump/.travis.yml rename to cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/pump/.travis.yml diff --git a/test/integration/test-fixtures/npm-lock/node_modules/pump/LICENSE b/cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/pump/LICENSE similarity index 100% rename from test/integration/test-fixtures/npm-lock/node_modules/pump/LICENSE rename to cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/pump/LICENSE diff --git a/test/integration/test-fixtures/npm-lock/node_modules/pump/README.md b/cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/pump/README.md similarity index 100% rename from test/integration/test-fixtures/npm-lock/node_modules/pump/README.md rename to cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/pump/README.md diff --git a/test/integration/test-fixtures/npm-lock/node_modules/pump/index.js b/cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/pump/index.js similarity index 100% rename from test/integration/test-fixtures/npm-lock/node_modules/pump/index.js rename to cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/pump/index.js diff --git a/test/integration/test-fixtures/npm-lock/node_modules/pump/package.json b/cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/pump/package.json similarity index 100% rename from test/integration/test-fixtures/npm-lock/node_modules/pump/package.json rename to cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/pump/package.json diff --git a/test/integration/test-fixtures/npm-lock/node_modules/pump/test-browser.js b/cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/pump/test-browser.js similarity index 100% rename from test/integration/test-fixtures/npm-lock/node_modules/pump/test-browser.js rename to cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/pump/test-browser.js diff --git a/test/integration/test-fixtures/npm-lock/node_modules/pump/test-node.js b/cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/pump/test-node.js similarity index 100% rename from test/integration/test-fixtures/npm-lock/node_modules/pump/test-node.js rename to cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/pump/test-node.js diff --git a/test/integration/test-fixtures/npm-lock/node_modules/wrappy/LICENSE b/cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/wrappy/LICENSE similarity index 100% rename from test/integration/test-fixtures/npm-lock/node_modules/wrappy/LICENSE rename to cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/wrappy/LICENSE diff --git a/test/integration/test-fixtures/npm-lock/node_modules/wrappy/README.md b/cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/wrappy/README.md similarity index 100% rename from test/integration/test-fixtures/npm-lock/node_modules/wrappy/README.md rename to cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/wrappy/README.md diff --git a/test/integration/test-fixtures/npm-lock/node_modules/wrappy/package-lock.json b/cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/wrappy/package-lock.json similarity index 100% rename from test/integration/test-fixtures/npm-lock/node_modules/wrappy/package-lock.json rename to cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/wrappy/package-lock.json diff --git a/test/integration/test-fixtures/npm-lock/node_modules/wrappy/package.json b/cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/wrappy/package.json similarity index 100% rename from test/integration/test-fixtures/npm-lock/node_modules/wrappy/package.json rename to cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/wrappy/package.json diff --git a/test/integration/test-fixtures/npm-lock/node_modules/wrappy/wrappy.js b/cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/wrappy/wrappy.js similarity index 100% rename from test/integration/test-fixtures/npm-lock/node_modules/wrappy/wrappy.js rename to cmd/syft/internal/test/integration/test-fixtures/npm-lock/node_modules/wrappy/wrappy.js diff --git a/test/integration/test-fixtures/npm-lock/package-lock.json b/cmd/syft/internal/test/integration/test-fixtures/npm-lock/package-lock.json similarity index 100% rename from test/integration/test-fixtures/npm-lock/package-lock.json rename to cmd/syft/internal/test/integration/test-fixtures/npm-lock/package-lock.json diff --git a/test/integration/test-fixtures/npm-lock/package.json b/cmd/syft/internal/test/integration/test-fixtures/npm-lock/package.json similarity index 100% rename from test/integration/test-fixtures/npm-lock/package.json rename to cmd/syft/internal/test/integration/test-fixtures/npm-lock/package.json diff --git a/test/integration/test-fixtures/yarn-lock/node_modules/async/LICENSE b/cmd/syft/internal/test/integration/test-fixtures/yarn-lock/node_modules/async/LICENSE similarity index 100% rename from test/integration/test-fixtures/yarn-lock/node_modules/async/LICENSE rename to cmd/syft/internal/test/integration/test-fixtures/yarn-lock/node_modules/async/LICENSE diff --git a/test/integration/test-fixtures/yarn-lock/node_modules/async/bower.json b/cmd/syft/internal/test/integration/test-fixtures/yarn-lock/node_modules/async/bower.json similarity index 100% rename from test/integration/test-fixtures/yarn-lock/node_modules/async/bower.json rename to cmd/syft/internal/test/integration/test-fixtures/yarn-lock/node_modules/async/bower.json diff --git a/test/integration/test-fixtures/yarn-lock/node_modules/async/package.json b/cmd/syft/internal/test/integration/test-fixtures/yarn-lock/node_modules/async/package.json similarity index 100% rename from test/integration/test-fixtures/yarn-lock/node_modules/async/package.json rename to cmd/syft/internal/test/integration/test-fixtures/yarn-lock/node_modules/async/package.json diff --git a/test/integration/test-fixtures/yarn-lock/node_modules/merge-objects/LICENSE.md b/cmd/syft/internal/test/integration/test-fixtures/yarn-lock/node_modules/merge-objects/LICENSE.md similarity index 100% rename from test/integration/test-fixtures/yarn-lock/node_modules/merge-objects/LICENSE.md rename to cmd/syft/internal/test/integration/test-fixtures/yarn-lock/node_modules/merge-objects/LICENSE.md diff --git a/test/integration/test-fixtures/yarn-lock/node_modules/merge-objects/package.json b/cmd/syft/internal/test/integration/test-fixtures/yarn-lock/node_modules/merge-objects/package.json similarity index 100% rename from test/integration/test-fixtures/yarn-lock/node_modules/merge-objects/package.json rename to cmd/syft/internal/test/integration/test-fixtures/yarn-lock/node_modules/merge-objects/package.json diff --git a/test/integration/test-fixtures/yarn-lock/node_modules/resize-observer-polyfill/LICENSE b/cmd/syft/internal/test/integration/test-fixtures/yarn-lock/node_modules/resize-observer-polyfill/LICENSE similarity index 100% rename from test/integration/test-fixtures/yarn-lock/node_modules/resize-observer-polyfill/LICENSE rename to cmd/syft/internal/test/integration/test-fixtures/yarn-lock/node_modules/resize-observer-polyfill/LICENSE diff --git a/test/integration/test-fixtures/yarn-lock/node_modules/resize-observer-polyfill/package.json b/cmd/syft/internal/test/integration/test-fixtures/yarn-lock/node_modules/resize-observer-polyfill/package.json similarity index 100% rename from test/integration/test-fixtures/yarn-lock/node_modules/resize-observer-polyfill/package.json rename to cmd/syft/internal/test/integration/test-fixtures/yarn-lock/node_modules/resize-observer-polyfill/package.json diff --git a/test/integration/test-fixtures/yarn-lock/node_modules/should-type/LICENSE b/cmd/syft/internal/test/integration/test-fixtures/yarn-lock/node_modules/should-type/LICENSE similarity index 100% rename from test/integration/test-fixtures/yarn-lock/node_modules/should-type/LICENSE rename to cmd/syft/internal/test/integration/test-fixtures/yarn-lock/node_modules/should-type/LICENSE diff --git a/test/integration/test-fixtures/yarn-lock/node_modules/should-type/package.json b/cmd/syft/internal/test/integration/test-fixtures/yarn-lock/node_modules/should-type/package.json similarity index 100% rename from test/integration/test-fixtures/yarn-lock/node_modules/should-type/package.json rename to cmd/syft/internal/test/integration/test-fixtures/yarn-lock/node_modules/should-type/package.json diff --git a/test/integration/test-fixtures/yarn-lock/package.json b/cmd/syft/internal/test/integration/test-fixtures/yarn-lock/package.json similarity index 100% rename from test/integration/test-fixtures/yarn-lock/package.json rename to cmd/syft/internal/test/integration/test-fixtures/yarn-lock/package.json diff --git a/test/integration/test-fixtures/yarn-lock/packages/nested-package/node_modules/async/LICENSE b/cmd/syft/internal/test/integration/test-fixtures/yarn-lock/packages/nested-package/node_modules/async/LICENSE similarity index 100% rename from test/integration/test-fixtures/yarn-lock/packages/nested-package/node_modules/async/LICENSE rename to cmd/syft/internal/test/integration/test-fixtures/yarn-lock/packages/nested-package/node_modules/async/LICENSE diff --git a/test/integration/test-fixtures/yarn-lock/packages/nested-package/node_modules/async/bower.json b/cmd/syft/internal/test/integration/test-fixtures/yarn-lock/packages/nested-package/node_modules/async/bower.json similarity index 100% rename from test/integration/test-fixtures/yarn-lock/packages/nested-package/node_modules/async/bower.json rename to cmd/syft/internal/test/integration/test-fixtures/yarn-lock/packages/nested-package/node_modules/async/bower.json diff --git a/test/integration/test-fixtures/yarn-lock/packages/nested-package/node_modules/async/component.json b/cmd/syft/internal/test/integration/test-fixtures/yarn-lock/packages/nested-package/node_modules/async/component.json similarity index 100% rename from test/integration/test-fixtures/yarn-lock/packages/nested-package/node_modules/async/component.json rename to cmd/syft/internal/test/integration/test-fixtures/yarn-lock/packages/nested-package/node_modules/async/component.json diff --git a/test/integration/test-fixtures/yarn-lock/packages/nested-package/node_modules/async/package.json b/cmd/syft/internal/test/integration/test-fixtures/yarn-lock/packages/nested-package/node_modules/async/package.json similarity index 100% rename from test/integration/test-fixtures/yarn-lock/packages/nested-package/node_modules/async/package.json rename to cmd/syft/internal/test/integration/test-fixtures/yarn-lock/packages/nested-package/node_modules/async/package.json diff --git a/test/integration/test-fixtures/yarn-lock/packages/nested-package/package.json b/cmd/syft/internal/test/integration/test-fixtures/yarn-lock/packages/nested-package/package.json similarity index 100% rename from test/integration/test-fixtures/yarn-lock/packages/nested-package/package.json rename to cmd/syft/internal/test/integration/test-fixtures/yarn-lock/packages/nested-package/package.json diff --git a/test/integration/test-fixtures/yarn-lock/yarn.lock b/cmd/syft/internal/test/integration/test-fixtures/yarn-lock/yarn.lock similarity index 100% rename from test/integration/test-fixtures/yarn-lock/yarn.lock rename to cmd/syft/internal/test/integration/test-fixtures/yarn-lock/yarn.lock diff --git a/test/integration/utils_test.go b/cmd/syft/internal/test/integration/utils_test.go similarity index 98% rename from test/integration/utils_test.go rename to cmd/syft/internal/test/integration/utils_test.go index 58b300756..cfca47834 100644 --- a/test/integration/utils_test.go +++ b/cmd/syft/internal/test/integration/utils_test.go @@ -8,7 +8,7 @@ import ( "github.com/anchore/clio" "github.com/anchore/stereoscope/pkg/imagetest" - "github.com/anchore/syft/cmd/syft/cli/options" + "github.com/anchore/syft/cmd/syft/internal/options" "github.com/anchore/syft/syft" "github.com/anchore/syft/syft/cataloging/pkgcataloging" "github.com/anchore/syft/syft/sbom" diff --git a/syft/cpe/cpe_test.go b/syft/cpe/cpe_test.go index 3d33e87e5..d6ed7a505 100644 --- a/syft/cpe/cpe_test.go +++ b/syft/cpe/cpe_test.go @@ -3,11 +3,11 @@ package cpe import ( "encoding/json" "fmt" - "github.com/google/go-cmp/cmp" "os" "strings" "testing" + "github.com/google/go-cmp/cmp" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) diff --git a/syft/format/decoders.go b/syft/format/decoders.go index 93afc3406..b74e3f894 100644 --- a/syft/format/decoders.go +++ b/syft/format/decoders.go @@ -1,7 +1,6 @@ package format import ( - "fmt" "io" "github.com/anchore/syft/syft/format/cyclonedxjson" @@ -12,10 +11,7 @@ import ( "github.com/anchore/syft/syft/sbom" ) -var ( - staticDecoders sbom.FormatDecoder - _ sbom.FormatDecoder = (*DecoderCollection)(nil) -) +var staticDecoders sbom.FormatDecoder func init() { staticDecoders = NewDecoderCollection(Decoders()...) @@ -31,61 +27,12 @@ func Decoders() []sbom.FormatDecoder { } } -type DecoderCollection struct { - decoders []sbom.FormatDecoder -} - -func NewDecoderCollection(decoders ...sbom.FormatDecoder) sbom.FormatDecoder { - return &DecoderCollection{ - decoders: decoders, - } -} - -// Decode takes a set of bytes and attempts to decode it into an SBOM relative to the decoders in the collection. -func (c *DecoderCollection) Decode(reader io.Reader) (*sbom.SBOM, sbom.FormatID, string, error) { - if reader == nil { - return nil, "", "", fmt.Errorf("no SBOM bytes provided") - } - var bestID sbom.FormatID - for _, d := range c.decoders { - id, version := d.Identify(reader) - if id == "" || version == "" { - if id != "" { - bestID = id - } - continue - } - - return d.Decode(reader) - } - - if bestID != "" { - return nil, bestID, "", fmt.Errorf("sbom format found to be %q but the version is not supported", bestID) - } - - return nil, "", "", fmt.Errorf("sbom format not recognized") -} - -// Identify takes a set of bytes and attempts to identify the format of the SBOM relative to the decoders in the collection. -func (c *DecoderCollection) Identify(reader io.Reader) (sbom.FormatID, string) { - if reader == nil { - return "", "" - } - for _, d := range c.decoders { - id, version := d.Identify(reader) - if id != "" && version != "" { - return id, version - } - } - return "", "" -} - // Identify takes a set of bytes and attempts to identify the format of the SBOM. -func Identify(reader io.Reader) (sbom.FormatID, string) { +func Identify(reader io.ReadSeeker) (sbom.FormatID, string) { return staticDecoders.Identify(reader) } // Decode takes a set of bytes and attempts to decode it into an SBOM. -func Decode(reader io.Reader) (*sbom.SBOM, sbom.FormatID, string, error) { +func Decode(reader io.ReadSeeker) (*sbom.SBOM, sbom.FormatID, string, error) { return staticDecoders.Decode(reader) } diff --git a/syft/format/decoders_collection.go b/syft/format/decoders_collection.go new file mode 100644 index 000000000..16227510b --- /dev/null +++ b/syft/format/decoders_collection.go @@ -0,0 +1,59 @@ +package format + +import ( + "fmt" + "io" + + "github.com/anchore/syft/syft/sbom" +) + +var _ sbom.FormatDecoder = (*DecoderCollection)(nil) + +type DecoderCollection struct { + decoders []sbom.FormatDecoder +} + +func NewDecoderCollection(decoders ...sbom.FormatDecoder) sbom.FormatDecoder { + return &DecoderCollection{ + decoders: decoders, + } +} + +// Decode takes a set of bytes and attempts to decode it into an SBOM relative to the decoders in the collection. +func (c *DecoderCollection) Decode(reader io.Reader) (*sbom.SBOM, sbom.FormatID, string, error) { + if reader == nil { + return nil, "", "", fmt.Errorf("no SBOM bytes provided") + } + var bestID sbom.FormatID + for _, d := range c.decoders { + id, version := d.Identify(reader) + if id == "" || version == "" { + if id != "" { + bestID = id + } + continue + } + + return d.Decode(reader) + } + + if bestID != "" { + return nil, bestID, "", fmt.Errorf("sbom format found to be %q but the version is not supported", bestID) + } + + return nil, "", "", fmt.Errorf("sbom format not recognized") +} + +// Identify takes a set of bytes and attempts to identify the format of the SBOM relative to the decoders in the collection. +func (c *DecoderCollection) Identify(reader io.Reader) (sbom.FormatID, string) { + if reader == nil { + return "", "" + } + for _, d := range c.decoders { + id, version := d.Identify(reader) + if id != "" && version != "" { + return id, version + } + } + return "", "" +} diff --git a/syft/format/decoders_test.go b/syft/format/decoders_collection_test.go similarity index 100% rename from syft/format/decoders_test.go rename to syft/format/decoders_collection_test.go diff --git a/syft/format/encoders.go b/syft/format/encoders.go index ffe7c59cc..71af0705f 100644 --- a/syft/format/encoders.go +++ b/syft/format/encoders.go @@ -1,143 +1,225 @@ package format import ( - "bytes" "fmt" - "regexp" - "sort" - "strings" - "github.com/scylladb/go-set/strset" + "github.com/hashicorp/go-multierror" - "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/syft/format/cyclonedxjson" + "github.com/anchore/syft/syft/format/cyclonedxxml" + "github.com/anchore/syft/syft/format/github" + "github.com/anchore/syft/syft/format/spdxjson" + "github.com/anchore/syft/syft/format/spdxtagvalue" + "github.com/anchore/syft/syft/format/syftjson" + "github.com/anchore/syft/syft/format/table" + "github.com/anchore/syft/syft/format/template" + "github.com/anchore/syft/syft/format/text" "github.com/anchore/syft/syft/sbom" ) -type EncoderCollection struct { - encoders []sbom.FormatEncoder +const AllVersions = "all-versions" + +type EncodersConfig struct { + Template template.EncoderConfig + SyftJSON syftjson.EncoderConfig + SPDXJSON spdxjson.EncoderConfig + SPDXTagValue spdxtagvalue.EncoderConfig + CyclonedxJSON cyclonedxjson.EncoderConfig + CyclonedxXML cyclonedxxml.EncoderConfig } -func NewEncoderCollection(encoders ...sbom.FormatEncoder) *EncoderCollection { - return &EncoderCollection{ - encoders: encoders, - } +func Encoders() []sbom.FormatEncoder { + encs, _ := DefaultEncodersConfig().Encoders() + return encs } -// IDs returns all format IDs represented in the collection. -func (e EncoderCollection) IDs() []sbom.FormatID { - idSet := strset.New() - for _, f := range e.encoders { - idSet.Add(string(f.ID())) +func DefaultEncodersConfig() EncodersConfig { + cfg := EncodersConfig{ + Template: template.DefaultEncoderConfig(), + SyftJSON: syftjson.DefaultEncoderConfig(), + SPDXJSON: spdxjson.DefaultEncoderConfig(), + SPDXTagValue: spdxtagvalue.DefaultEncoderConfig(), + CyclonedxJSON: cyclonedxjson.DefaultEncoderConfig(), + CyclonedxXML: cyclonedxxml.DefaultEncoderConfig(), } - idList := idSet.List() - sort.Strings(idList) + // empty value means to support all versions + cfg.SPDXJSON.Version = AllVersions + cfg.SPDXTagValue.Version = AllVersions + cfg.CyclonedxJSON.Version = AllVersions + cfg.CyclonedxXML.Version = AllVersions - var ids []sbom.FormatID - for _, id := range idList { - ids = append(ids, sbom.FormatID(id)) - } - - return ids + return cfg } -// NameVersions returns all formats that are supported by the collection as a list of "name@version" strings. -func (e EncoderCollection) NameVersions() []string { - set := strset.New() - for _, f := range e.encoders { - if f.Version() == sbom.AnyVersion { - set.Add(string(f.ID())) - } else { - set.Add(fmt.Sprintf("%s@%s", f.ID(), f.Version())) - } +func (o EncodersConfig) Encoders() ([]sbom.FormatEncoder, error) { + var l encodersList + + if o.Template.TemplatePath != "" { + l.addWithErr(template.ID)(o.templateEncoders()) } - list := set.List() - sort.Strings(list) + l.addWithErr(syftjson.ID)(o.syftJSONEncoders()) + l.add(table.ID)(table.NewFormatEncoder()) + l.add(text.ID)(text.NewFormatEncoder()) + l.add(github.ID)(github.NewFormatEncoder()) + l.addWithErr(cyclonedxxml.ID)(o.cyclonedxXMLEncoders()) + l.addWithErr(cyclonedxjson.ID)(o.cyclonedxJSONEncoders()) + l.addWithErr(spdxjson.ID)(o.spdxJSONEncoders()) + l.addWithErr(spdxtagvalue.ID)(o.spdxTagValueEncoders()) - return list + return l.encoders, l.err } -// Aliases returns all format aliases represented in the collection (where an ID would be "spdx-tag-value" the alias would be "spdx"). -func (e EncoderCollection) Aliases() []string { - aliases := strset.New() - for _, f := range e.encoders { - aliases.Add(f.Aliases()...) - } - lst := aliases.List() - sort.Strings(lst) - return lst +func (o EncodersConfig) templateEncoders() ([]sbom.FormatEncoder, error) { + enc, err := template.NewFormatEncoder(template.EncoderConfig{ + TemplatePath: o.Template.TemplatePath, + }) + return []sbom.FormatEncoder{enc}, err } -// Get returns the contained encoder for a given format name and version. -func (e EncoderCollection) Get(name string, version string) sbom.FormatEncoder { - log.WithFields("name", name, "version", version).Trace("looking for matching encoder") +func (o EncodersConfig) syftJSONEncoders() ([]sbom.FormatEncoder, error) { + enc, err := syftjson.NewFormatEncoderWithConfig(o.SyftJSON) + return []sbom.FormatEncoder{enc}, err +} - name = cleanFormatName(name) - var mostRecentFormat sbom.FormatEncoder +func (o EncodersConfig) cyclonedxXMLEncoders() ([]sbom.FormatEncoder, error) { + var ( + encs []sbom.FormatEncoder + errs error + ) - for _, f := range e.encoders { - log.WithFields("name", f.ID(), "version", f.Version(), "aliases", f.Aliases()).Trace("considering format") - names := []string{string(f.ID())} - names = append(names, f.Aliases()...) - for _, n := range names { - if cleanFormatName(n) == name && versionMatches(f.Version(), version) { - if mostRecentFormat == nil || f.Version() > mostRecentFormat.Version() { - mostRecentFormat = f - } - } - } - } + cfg := o.CyclonedxXML - if mostRecentFormat != nil { - log.WithFields("name", mostRecentFormat.ID(), "version", mostRecentFormat.Version()).Trace("found matching encoder") + var versions []string + if cfg.Version == AllVersions { + versions = cyclonedxxml.SupportedVersions() } else { - log.WithFields("search-name", name, "search-version", version).Trace("no matching encoder found") + versions = []string{cfg.Version} } - return mostRecentFormat -} - -// GetByString accepts a name@version string, such as: -// - json -// - spdx-json@2.1 -// - cdx@1.5 -func (e EncoderCollection) GetByString(s string) sbom.FormatEncoder { - parts := strings.SplitN(s, "@", 2) - version := sbom.AnyVersion - if len(parts) > 1 { - version = parts[1] + for _, v := range versions { + cfg.Version = v + enc, err := cyclonedxxml.NewFormatEncoderWithConfig(cfg) + if err != nil { + errs = multierror.Append(errs, err) + } else { + encs = append(encs, enc) + } } - return e.Get(parts[0], version) + return encs, errs } -func versionMatches(version string, match string) bool { - if version == sbom.AnyVersion || match == sbom.AnyVersion { - return true +func (o EncodersConfig) cyclonedxJSONEncoders() ([]sbom.FormatEncoder, error) { + var ( + encs []sbom.FormatEncoder + errs error + ) + + cfg := o.CyclonedxJSON + + var versions []string + if cfg.Version == AllVersions { + versions = cyclonedxjson.SupportedVersions() + } else { + versions = []string{cfg.Version} } - match = strings.ReplaceAll(match, ".", "\\.") - match = strings.ReplaceAll(match, "*", ".*") - match = fmt.Sprintf("^%s(\\..*)*$", match) - matcher, err := regexp.Compile(match) - if err != nil { - return false + for _, v := range versions { + cfg.Version = v + enc, err := cyclonedxjson.NewFormatEncoderWithConfig(cfg) + if err != nil { + errs = multierror.Append(errs, err) + } else { + encs = append(encs, enc) + } } - return matcher.MatchString(version) + return encs, errs } -func cleanFormatName(name string) string { - r := strings.NewReplacer("-", "", "_", "") - return strings.ToLower(r.Replace(name)) -} +func (o EncodersConfig) spdxJSONEncoders() ([]sbom.FormatEncoder, error) { + var ( + encs []sbom.FormatEncoder + errs error + ) -// Encode takes all SBOM elements and a format option and encodes an SBOM document. -func Encode(s sbom.SBOM, f sbom.FormatEncoder) ([]byte, error) { - buff := bytes.Buffer{} + cfg := o.SPDXJSON - if err := f.Encode(&buff, s); err != nil { - return nil, fmt.Errorf("unable to encode sbom: %w", err) + var versions []string + if cfg.Version == AllVersions { + versions = spdxjson.SupportedVersions() + } else { + versions = []string{cfg.Version} } - return buff.Bytes(), nil + for _, v := range versions { + cfg.Version = v + enc, err := spdxjson.NewFormatEncoderWithConfig(cfg) + if err != nil { + errs = multierror.Append(errs, err) + } else { + encs = append(encs, enc) + } + } + return encs, errs +} + +func (o EncodersConfig) spdxTagValueEncoders() ([]sbom.FormatEncoder, error) { + var ( + encs []sbom.FormatEncoder + errs error + ) + + cfg := o.SPDXTagValue + + var versions []string + if cfg.Version == AllVersions { + versions = spdxtagvalue.SupportedVersions() + } else { + versions = []string{cfg.Version} + } + + for _, v := range versions { + cfg.Version = v + enc, err := spdxtagvalue.NewFormatEncoderWithConfig(cfg) + if err != nil { + errs = multierror.Append(errs, err) + } else { + encs = append(encs, enc) + } + } + return encs, errs +} + +type encodersList struct { + encoders []sbom.FormatEncoder + err error +} + +func (l *encodersList) addWithErr(name sbom.FormatID) func([]sbom.FormatEncoder, error) { + return func(encs []sbom.FormatEncoder, err error) { + if err != nil { + l.err = multierror.Append(l.err, fmt.Errorf("unable to configure %q format encoder: %w", name, err)) + return + } + for _, enc := range encs { + if enc == nil { + l.err = multierror.Append(l.err, fmt.Errorf("unable to configure %q format encoder: nil encoder returned", name)) + continue + } + l.encoders = append(l.encoders, enc) + } + } +} + +func (l *encodersList) add(name sbom.FormatID) func(...sbom.FormatEncoder) { + return func(encs ...sbom.FormatEncoder) { + for _, enc := range encs { + if enc == nil { + l.err = multierror.Append(l.err, fmt.Errorf("unable to configure %q format encoder: nil encoder returned", name)) + continue + } + l.encoders = append(l.encoders, enc) + } + } } diff --git a/syft/format/encoders_collection.go b/syft/format/encoders_collection.go new file mode 100644 index 000000000..ffe7c59cc --- /dev/null +++ b/syft/format/encoders_collection.go @@ -0,0 +1,143 @@ +package format + +import ( + "bytes" + "fmt" + "regexp" + "sort" + "strings" + + "github.com/scylladb/go-set/strset" + + "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/syft/sbom" +) + +type EncoderCollection struct { + encoders []sbom.FormatEncoder +} + +func NewEncoderCollection(encoders ...sbom.FormatEncoder) *EncoderCollection { + return &EncoderCollection{ + encoders: encoders, + } +} + +// IDs returns all format IDs represented in the collection. +func (e EncoderCollection) IDs() []sbom.FormatID { + idSet := strset.New() + for _, f := range e.encoders { + idSet.Add(string(f.ID())) + } + + idList := idSet.List() + sort.Strings(idList) + + var ids []sbom.FormatID + for _, id := range idList { + ids = append(ids, sbom.FormatID(id)) + } + + return ids +} + +// NameVersions returns all formats that are supported by the collection as a list of "name@version" strings. +func (e EncoderCollection) NameVersions() []string { + set := strset.New() + for _, f := range e.encoders { + if f.Version() == sbom.AnyVersion { + set.Add(string(f.ID())) + } else { + set.Add(fmt.Sprintf("%s@%s", f.ID(), f.Version())) + } + } + + list := set.List() + sort.Strings(list) + + return list +} + +// Aliases returns all format aliases represented in the collection (where an ID would be "spdx-tag-value" the alias would be "spdx"). +func (e EncoderCollection) Aliases() []string { + aliases := strset.New() + for _, f := range e.encoders { + aliases.Add(f.Aliases()...) + } + lst := aliases.List() + sort.Strings(lst) + return lst +} + +// Get returns the contained encoder for a given format name and version. +func (e EncoderCollection) Get(name string, version string) sbom.FormatEncoder { + log.WithFields("name", name, "version", version).Trace("looking for matching encoder") + + name = cleanFormatName(name) + var mostRecentFormat sbom.FormatEncoder + + for _, f := range e.encoders { + log.WithFields("name", f.ID(), "version", f.Version(), "aliases", f.Aliases()).Trace("considering format") + names := []string{string(f.ID())} + names = append(names, f.Aliases()...) + for _, n := range names { + if cleanFormatName(n) == name && versionMatches(f.Version(), version) { + if mostRecentFormat == nil || f.Version() > mostRecentFormat.Version() { + mostRecentFormat = f + } + } + } + } + + if mostRecentFormat != nil { + log.WithFields("name", mostRecentFormat.ID(), "version", mostRecentFormat.Version()).Trace("found matching encoder") + } else { + log.WithFields("search-name", name, "search-version", version).Trace("no matching encoder found") + } + + return mostRecentFormat +} + +// GetByString accepts a name@version string, such as: +// - json +// - spdx-json@2.1 +// - cdx@1.5 +func (e EncoderCollection) GetByString(s string) sbom.FormatEncoder { + parts := strings.SplitN(s, "@", 2) + version := sbom.AnyVersion + if len(parts) > 1 { + version = parts[1] + } + return e.Get(parts[0], version) +} + +func versionMatches(version string, match string) bool { + if version == sbom.AnyVersion || match == sbom.AnyVersion { + return true + } + + match = strings.ReplaceAll(match, ".", "\\.") + match = strings.ReplaceAll(match, "*", ".*") + match = fmt.Sprintf("^%s(\\..*)*$", match) + matcher, err := regexp.Compile(match) + if err != nil { + return false + } + return matcher.MatchString(version) +} + +func cleanFormatName(name string) string { + r := strings.NewReplacer("-", "", "_", "") + return strings.ToLower(r.Replace(name)) +} + +// Encode takes all SBOM elements and a format option and encodes an SBOM document. +func Encode(s sbom.SBOM, f sbom.FormatEncoder) ([]byte, error) { + buff := bytes.Buffer{} + + if err := f.Encode(&buff, s); err != nil { + return nil, fmt.Errorf("unable to encode sbom: %w", err) + } + + return buff.Bytes(), nil +} diff --git a/syft/format/encoders_collection_test.go b/syft/format/encoders_collection_test.go new file mode 100644 index 000000000..3e8128fb6 --- /dev/null +++ b/syft/format/encoders_collection_test.go @@ -0,0 +1,111 @@ +package format + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/anchore/syft/syft/sbom" +) + +func Test_versionMatches(t *testing.T) { + tests := []struct { + name string + version string + match string + matches bool + }{ + { + name: "any version matches number", + version: string(sbom.AnyVersion), + match: "6", + matches: true, + }, + { + name: "number matches any version", + version: "6", + match: string(sbom.AnyVersion), + matches: true, + }, + { + name: "same number matches", + version: "3", + match: "3", + matches: true, + }, + { + name: "same major number matches", + version: "3.1", + match: "3", + matches: true, + }, + { + name: "same minor number matches", + version: "3.1", + match: "3.1", + matches: true, + }, + { + name: "wildcard-version matches minor", + version: "7.1.3", + match: "7.*", + matches: true, + }, + { + name: "wildcard-version matches patch", + version: "7.4.8", + match: "7.4.*", + matches: true, + }, + { + name: "sub-version matches major", + version: "7.19.11", + match: "7", + matches: true, + }, + { + name: "sub-version matches minor", + version: "7.55.2", + match: "7.55", + matches: true, + }, + { + name: "sub-version matches patch", + version: "7.32.6", + match: "7.32.6", + matches: true, + }, + // negative tests + { + name: "different number does not match", + version: "3", + match: "4", + matches: false, + }, + { + name: "sub-version doesn't match major", + version: "7.2.5", + match: "8.2.5", + matches: false, + }, + { + name: "sub-version doesn't match minor", + version: "7.2.9", + match: "7.1", + matches: false, + }, + { + name: "sub-version doesn't match patch", + version: "7.32.6", + match: "7.32.5", + matches: false, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + matches := versionMatches(test.version, test.match) + assert.Equal(t, test.matches, matches) + }) + } +} diff --git a/syft/format/encoders_test.go b/syft/format/encoders_test.go index 3e8128fb6..7595725da 100644 --- a/syft/format/encoders_test.go +++ b/syft/format/encoders_test.go @@ -3,109 +3,133 @@ package format import ( "testing" + "github.com/scylladb/go-set/strset" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/anchore/syft/internal" + "github.com/anchore/syft/syft/format/cyclonedxjson" + "github.com/anchore/syft/syft/format/cyclonedxxml" + "github.com/anchore/syft/syft/format/internal/cyclonedxutil" + "github.com/anchore/syft/syft/format/internal/spdxutil" + "github.com/anchore/syft/syft/format/spdxjson" + "github.com/anchore/syft/syft/format/spdxtagvalue" + "github.com/anchore/syft/syft/format/syftjson" + "github.com/anchore/syft/syft/format/template" "github.com/anchore/syft/syft/sbom" ) -func Test_versionMatches(t *testing.T) { - tests := []struct { - name string - version string - match string - matches bool - }{ - { - name: "any version matches number", - version: string(sbom.AnyVersion), - match: "6", - matches: true, - }, - { - name: "number matches any version", - version: "6", - match: string(sbom.AnyVersion), - matches: true, - }, - { - name: "same number matches", - version: "3", - match: "3", - matches: true, - }, - { - name: "same major number matches", - version: "3.1", - match: "3", - matches: true, - }, - { - name: "same minor number matches", - version: "3.1", - match: "3.1", - matches: true, - }, - { - name: "wildcard-version matches minor", - version: "7.1.3", - match: "7.*", - matches: true, - }, - { - name: "wildcard-version matches patch", - version: "7.4.8", - match: "7.4.*", - matches: true, - }, - { - name: "sub-version matches major", - version: "7.19.11", - match: "7", - matches: true, - }, - { - name: "sub-version matches minor", - version: "7.55.2", - match: "7.55", - matches: true, - }, - { - name: "sub-version matches patch", - version: "7.32.6", - match: "7.32.6", - matches: true, - }, - // negative tests - { - name: "different number does not match", - version: "3", - match: "4", - matches: false, - }, - { - name: "sub-version doesn't match major", - version: "7.2.5", - match: "8.2.5", - matches: false, - }, - { - name: "sub-version doesn't match minor", - version: "7.2.9", - match: "7.1", - matches: false, - }, - { - name: "sub-version doesn't match patch", - version: "7.32.6", - match: "7.32.5", - matches: false, - }, +func Test_Encoders(t *testing.T) { + // this is an explicit test that the default encoders and encoders are the same and does not error + encs, err := DefaultEncodersConfig().Encoders() + require.NoError(t, err) + assert.NotEmpty(t, encs) + + expected := expectedDefaultEncoders() + assertHasEncoders(t, expected, encs) + assertHasEncoders(t, expected, Encoders()) +} + +func expectedDefaultEncoders() *strset.Set { + expected := strset.New() + // note: template is not expected in the default encoders + expected.Add("syft-json@" + internal.JSONSchemaVersion) // TODO: support multiple versions + expected.Add("syft-table@") // no version + expected.Add("syft-text@") // no version + expected.Add("github-json@") // no version + for _, v := range spdxjson.SupportedVersions() { + expected.Add("spdx-json@" + v) + } + for _, v := range spdxtagvalue.SupportedVersions() { + expected.Add("spdx-tag-value@" + v) + } + for _, v := range cyclonedxjson.SupportedVersions() { + expected.Add("cyclonedx-json@" + v) + } + for _, v := range cyclonedxxml.SupportedVersions() { + expected.Add("cyclonedx-xml@" + v) + } + return expected +} + +func assertHasEncoders(t *testing.T, expected *strset.Set, encs []sbom.FormatEncoder) { + for _, enc := range encs { + assert.True(t, expected.Has(string(enc.ID())+"@"+enc.Version()), "missing: "+string(enc.ID())+"@"+enc.Version()) } - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - matches := versionMatches(test.version, test.match) - assert.Equal(t, test.matches, matches) + if t.Failed() { + t.Log("got encoders:") + for _, enc := range encs { + t.Log(" - " + string(enc.ID()) + "@" + enc.Version()) + } + } +} + +func TestEncodersConfig_Encoders(t *testing.T) { + + tests := []struct { + name string + cfg EncodersConfig + want *strset.Set + wantErr require.ErrorAssertionFunc + }{ + { + name: "default", + cfg: DefaultEncodersConfig(), + want: expectedDefaultEncoders(), + }, + { + name: "with template", + cfg: func() EncodersConfig { + cfg := DefaultEncodersConfig() + cfg.Template.TemplatePath = "foo" + return cfg + }(), + want: func() *strset.Set { + expected := expectedDefaultEncoders() + expected.Add("template@") + return expected + }(), + }, + { + name: "explicit versions template", + cfg: EncodersConfig{ + Template: template.DefaultEncoderConfig(), + SyftJSON: syftjson.DefaultEncoderConfig(), + SPDXJSON: spdxjson.DefaultEncoderConfig(), + SPDXTagValue: spdxtagvalue.DefaultEncoderConfig(), + CyclonedxJSON: cyclonedxjson.DefaultEncoderConfig(), + CyclonedxXML: cyclonedxxml.DefaultEncoderConfig(), + }, + want: func() *strset.Set { + expected := strset.New() + // note: template is not expected in the default encoders + expected.Add("syft-json@" + internal.JSONSchemaVersion) // TODO: support multiple versions + expected.Add("syft-table@") // no version + expected.Add("syft-text@") // no version + expected.Add("github-json@") // no version + expected.Add("spdx-json@" + spdxutil.DefaultVersion) + expected.Add("spdx-tag-value@" + spdxutil.DefaultVersion) + expected.Add("cyclonedx-json@" + cyclonedxutil.DefaultVersion) + expected.Add("cyclonedx-xml@" + cyclonedxutil.DefaultVersion) + + return expected + }(), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.wantErr == nil { + tt.wantErr = require.NoError + } + + got, err := tt.cfg.Encoders() + tt.wantErr(t, err) + if err != nil { + return + } + + assertHasEncoders(t, tt.want, got) }) } } diff --git a/test/cli/all_formats_expressible_test.go b/test/cli/all_formats_expressible_test.go index 9fb5bc8da..065ae5f14 100644 --- a/test/cli/all_formats_expressible_test.go +++ b/test/cli/all_formats_expressible_test.go @@ -6,7 +6,6 @@ import ( "github.com/stretchr/testify/require" - "github.com/anchore/syft/cmd/syft/cli/options" "github.com/anchore/syft/syft/format" "github.com/anchore/syft/syft/format/template" ) @@ -22,12 +21,7 @@ func TestAllFormatsExpressible(t *testing.T) { assertSuccessfulReturnCode, } - opts := options.DefaultOutput() - require.NoError(t, opts.PostLoad()) - encoders, err := opts.Encoders() - require.NoError(t, err) - - encs := format.NewEncoderCollection(encoders...) + encs := format.NewEncoderCollection(format.Encoders()...) formatIDs := encs.IDs() require.NotEmpty(t, formatIDs) for _, o := range formatIDs { diff --git a/test/cli/convert_cmd_test.go b/test/cli/convert_cmd_test.go index 6cbd5b83c..2ec1455fc 100644 --- a/test/cli/convert_cmd_test.go +++ b/test/cli/convert_cmd_test.go @@ -4,19 +4,32 @@ import ( "fmt" "strings" "testing" + + "github.com/stretchr/testify/require" + + "github.com/anchore/syft/syft/format" + "github.com/anchore/syft/syft/format/cyclonedxjson" + "github.com/anchore/syft/syft/format/cyclonedxxml" + "github.com/anchore/syft/syft/format/spdxjson" + "github.com/anchore/syft/syft/format/spdxtagvalue" + "github.com/anchore/syft/syft/sbom" ) func TestConvertCmd(t *testing.T) { assertions := []traitAssertion{ - assertInOutput("PackageName: musl-utils"), + assertInOutput("musl-utils"), assertSuccessfulReturnCode, } tests := []struct { - from string - to string + from string + to string + expect sbom.FormatEncoder }{ - {from: "syft-json", to: "spdx-tag-value"}, + {from: "syft-json", to: "spdx-tag-value", expect: mustEncoder(spdxtagvalue.NewFormatEncoderWithConfig(spdxtagvalue.DefaultEncoderConfig()))}, + {from: "syft-json", to: "spdx-json", expect: mustEncoder(spdxjson.NewFormatEncoderWithConfig(spdxjson.DefaultEncoderConfig()))}, + {from: "syft-json", to: "cyclonedx-json", expect: mustEncoder(cyclonedxjson.NewFormatEncoderWithConfig(cyclonedxjson.DefaultEncoderConfig()))}, + {from: "syft-json", to: "cyclonedx-xml", expect: mustEncoder(cyclonedxxml.NewFormatEncoderWithConfig(cyclonedxxml.DefaultEncoderConfig()))}, } for _, test := range tests { @@ -41,6 +54,18 @@ func TestConvertCmd(t *testing.T) { traitFn(t, stdout, stderr, cmd.ProcessState.ExitCode()) } logOutputOnFailure(t, cmd, stdout, stderr) + + // let's make sure the output is valid relative to the expected format + foundID, _ := format.Identify(strings.NewReader(stdout)) + require.Equal(t, test.expect.ID(), foundID) + }) } } + +func mustEncoder(enc sbom.FormatEncoder, err error) sbom.FormatEncoder { + if err != nil { + panic(err) + } + return enc +} diff --git a/test/cli/test-fixtures/image-pkg-coverage b/test/cli/test-fixtures/image-pkg-coverage index 155332274..b46a39b2e 120000 --- a/test/cli/test-fixtures/image-pkg-coverage +++ b/test/cli/test-fixtures/image-pkg-coverage @@ -1 +1 @@ -../../integration/test-fixtures/image-pkg-coverage \ No newline at end of file +../../../cmd/syft/internal/test/integration/test-fixtures/image-pkg-coverage \ No newline at end of file diff --git a/test/integration/convert_test.go b/test/integration/convert_test.go deleted file mode 100644 index 913679cb8..000000000 --- a/test/integration/convert_test.go +++ /dev/null @@ -1,100 +0,0 @@ -package integration - -import ( - "fmt" - "os" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/anchore/syft/cmd/syft/cli/commands" - "github.com/anchore/syft/cmd/syft/cli/options" - "github.com/anchore/syft/syft/format" - "github.com/anchore/syft/syft/format/cyclonedxjson" - "github.com/anchore/syft/syft/format/cyclonedxxml" - "github.com/anchore/syft/syft/format/spdxjson" - "github.com/anchore/syft/syft/format/spdxtagvalue" - "github.com/anchore/syft/syft/format/syftjson" - "github.com/anchore/syft/syft/sbom" - "github.com/anchore/syft/syft/source" -) - -func mustEncoder(enc sbom.FormatEncoder, err error) sbom.FormatEncoder { - if err != nil { - panic(err) - } - return enc -} - -// TestConvertCmd tests if the converted SBOM is a valid document according -// to spec. -// TODO: This test can, but currently does not, check the converted SBOM content. It -// might be useful to do that in the future, once we gather a better understanding of -// what users expect from the convert command. -func TestConvertCmd(t *testing.T) { - tests := []struct { - name string - format sbom.FormatEncoder - }{ - { - name: "syft-json", - format: syftjson.NewFormatEncoder(), - }, - { - name: "spdx-json", - format: mustEncoder(spdxjson.NewFormatEncoderWithConfig(spdxjson.DefaultEncoderConfig())), - }, - { - name: "spdx-tag-value", - format: mustEncoder(spdxtagvalue.NewFormatEncoderWithConfig(spdxtagvalue.DefaultEncoderConfig())), - }, - { - name: "cyclonedx-json", - format: mustEncoder(cyclonedxjson.NewFormatEncoderWithConfig(cyclonedxjson.DefaultEncoderConfig())), - }, - { - name: "cyclonedx-xml", - format: mustEncoder(cyclonedxxml.NewFormatEncoderWithConfig(cyclonedxxml.DefaultEncoderConfig())), - }, - } - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - syftSbom, _ := catalogFixtureImage(t, "image-pkg-coverage", source.SquashedScope) - syftFormat := syftjson.NewFormatEncoder() - - syftFile, err := os.CreateTemp("", "test-convert-sbom-") - require.NoError(t, err) - defer func() { - _ = os.Remove(syftFile.Name()) - }() - - err = syftFormat.Encode(syftFile, syftSbom) - require.NoError(t, err) - - formatFile, err := os.CreateTemp("", "test-convert-sbom-") - require.NoError(t, err) - defer func() { - _ = os.Remove(syftFile.Name()) - }() - - opts := &commands.ConvertOptions{ - Output: options.DefaultOutput(), - } - opts.Outputs = []string{fmt.Sprintf("%s=%s", test.format.ID().String(), formatFile.Name())} - require.NoError(t, opts.PostLoad()) - - // stdout reduction of test noise - rescue := os.Stdout // keep backup of the real stdout - os.Stdout, _ = os.OpenFile(os.DevNull, os.O_APPEND|os.O_WRONLY, os.ModeAppend) - defer func() { - os.Stdout = rescue - }() - - err = commands.RunConvert(opts, syftFile.Name()) - require.NoError(t, err) - - foundID, _ := format.Identify(formatFile) - require.Equal(t, test.format.ID(), foundID) - }) - } -}