mirror of
https://github.com/anchore/syft.git
synced 2026-11-01 06:56:40 +01:00
Add "pretty" json configuration and change default behavior to be space-efficient (#2275)
* expose underlying format options Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * remove escape html options and address PR feedback Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * incorporate PR feedback Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * fix cli test Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> --------- Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
This commit is contained in:
@@ -1,6 +1,11 @@
|
||||
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"
|
||||
@@ -13,16 +18,34 @@ import (
|
||||
"github.com/anchore/syft/syft/sbom"
|
||||
)
|
||||
|
||||
var _ clio.PostLoader = (*Format)(nil)
|
||||
|
||||
// Format contains all user configuration for output formatting.
|
||||
type Format struct {
|
||||
Template FormatTemplate `yaml:"template" json:"template" mapstructure:"template"`
|
||||
JSON FormatJSON `yaml:"json" json:"json" mapstructure:"json"`
|
||||
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(),
|
||||
JSON: DefaultFormatJSON(),
|
||||
Template: DefaultFormatTemplate(),
|
||||
SyftJSON: DefaultFormatJSON(),
|
||||
SPDXJSON: DefaultFormatSPDXJSON(),
|
||||
CyclonedxJSON: DefaultFormatCyclonedxJSON(),
|
||||
CyclonedxXML: DefaultFormatCyclonedxXML(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,14 +55,75 @@ func (o *Format) Encoders() ([]sbom.FormatEncoder, error) {
|
||||
|
||||
// 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.JSON.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)(cycloneDxXMLEncoders())
|
||||
list.addWithErr(cyclonedxjson.ID)(cycloneDxJSONEncoders())
|
||||
list.addWithErr(spdxjson.ID)(spdxJSONEncoders())
|
||||
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
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
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 {
|
||||
return cyclonedxjson.EncoderConfig{
|
||||
Version: version,
|
||||
Pretty: *o.Pretty,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package options
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestFormatCyclonedxJSON_buildConfig(t *testing.T) {
|
||||
// assert when building the config that we respond to all possible fields
|
||||
|
||||
ft := &FormatCyclonedxJSON{}
|
||||
ft = setAllToNonZero(t, ft).(*FormatCyclonedxJSON)
|
||||
|
||||
subject := ft.buildConfig("Version")
|
||||
assertExpectedValue(t, subject)
|
||||
}
|
||||
|
||||
func setAllToNonZero(t testing.TB, structPtr any) any {
|
||||
// set all fields on the struct to non-zero values
|
||||
rt := reflect.TypeOf(structPtr)
|
||||
if rt.Kind() != reflect.Ptr || rt.Elem().Kind() != reflect.Struct {
|
||||
t.Fatal("expected a pointer to a struct")
|
||||
}
|
||||
|
||||
rv := reflect.ValueOf(structPtr).Elem()
|
||||
for i := 0; i < rt.Elem().NumField(); i++ {
|
||||
val := getNonZeroExampleValue(t, rv.Field(i).Interface(), rt.Elem().Field(i).Name)
|
||||
rv.Field(i).Set(reflect.ValueOf(val))
|
||||
}
|
||||
return structPtr
|
||||
}
|
||||
|
||||
func getNonZeroExampleValue(t testing.TB, v any, name string) any {
|
||||
switch v.(type) {
|
||||
case bool:
|
||||
return true
|
||||
case *bool:
|
||||
val := true
|
||||
return &val
|
||||
case string:
|
||||
return name
|
||||
}
|
||||
t.Fatalf("unsupported type: %T", v)
|
||||
return nil
|
||||
}
|
||||
|
||||
func assertExpectedValue(t *testing.T, structTy any) {
|
||||
rt := reflect.TypeOf(structTy)
|
||||
rv := reflect.ValueOf(structTy)
|
||||
|
||||
for i := 0; i < rt.NumField(); i++ {
|
||||
f := rt.Field(i)
|
||||
fieldValue := rv.Field(i)
|
||||
|
||||
if fieldValue.Type().Kind() == reflect.String {
|
||||
// use the field name as the expected value
|
||||
assert.Equalf(t, f.Name, fieldValue.String(), "field %q value differs", f.Name)
|
||||
} else {
|
||||
// use the zero value for the type
|
||||
if reflect.DeepEqual(fieldValue.Interface(), reflect.Zero(fieldValue.Type()).Interface()) {
|
||||
t.Errorf("field '%s' is zero", f.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
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 {
|
||||
return cyclonedxxml.EncoderConfig{
|
||||
Version: version,
|
||||
Pretty: *o.Pretty,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package options
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestFormatCyclonedxXML_buildConfig(t *testing.T) {
|
||||
// assert when building the config that we respond to all possible fields
|
||||
|
||||
ft := FormatCyclonedxXML{}
|
||||
ftp := setAllToNonZero(t, &ft).(*FormatCyclonedxXML)
|
||||
|
||||
subject := ftp.buildConfig("Version")
|
||||
assertExpectedValue(t, subject)
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package options
|
||||
|
||||
import (
|
||||
"github.com/anchore/syft/syft/format/syftjson"
|
||||
"github.com/anchore/syft/syft/sbom"
|
||||
)
|
||||
|
||||
type FormatJSON struct {
|
||||
Legacy bool `yaml:"legacy" json:"legacy" mapstructure:"legacy"`
|
||||
}
|
||||
|
||||
func DefaultFormatJSON() FormatJSON {
|
||||
return FormatJSON{
|
||||
Legacy: false,
|
||||
}
|
||||
}
|
||||
|
||||
func (o FormatJSON) formatEncoders() ([]sbom.FormatEncoder, error) {
|
||||
enc, err := syftjson.NewFormatEncoderWithConfig(
|
||||
syftjson.EncoderConfig{
|
||||
Legacy: o.Legacy,
|
||||
},
|
||||
)
|
||||
return []sbom.FormatEncoder{enc}, err
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
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 {
|
||||
return spdxjson.EncoderConfig{
|
||||
Version: v,
|
||||
Pretty: *o.Pretty,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package options
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestFormatSPDXJSON_buildConfig(t *testing.T) {
|
||||
// assert when building the config that we respond to all possible fields
|
||||
|
||||
ft := &FormatSPDXJSON{}
|
||||
ft = setAllToNonZero(t, ft).(*FormatSPDXJSON)
|
||||
|
||||
subject := ft.buildConfig("Version")
|
||||
assertExpectedValue(t, subject)
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package options
|
||||
|
||||
import (
|
||||
"github.com/anchore/syft/syft/format/syftjson"
|
||||
"github.com/anchore/syft/syft/sbom"
|
||||
)
|
||||
|
||||
type FormatSyftJSON struct {
|
||||
Legacy bool `yaml:"legacy" json:"legacy" mapstructure:"legacy"`
|
||||
Pretty *bool `yaml:"pretty" json:"pretty" mapstructure:"pretty"`
|
||||
}
|
||||
|
||||
func DefaultFormatJSON() FormatSyftJSON {
|
||||
return FormatSyftJSON{
|
||||
Legacy: false,
|
||||
}
|
||||
}
|
||||
|
||||
func (o FormatSyftJSON) formatEncoders() ([]sbom.FormatEncoder, error) {
|
||||
enc, err := syftjson.NewFormatEncoderWithConfig(o.buildConfig())
|
||||
return []sbom.FormatEncoder{enc}, err
|
||||
}
|
||||
|
||||
func (o FormatSyftJSON) buildConfig() syftjson.EncoderConfig {
|
||||
return syftjson.EncoderConfig{
|
||||
Legacy: o.Legacy,
|
||||
Pretty: *o.Pretty,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package options
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestFormatSyftJSON_buildConfig(t *testing.T) {
|
||||
// assert when building the config that we respond to all possible fields
|
||||
|
||||
ft := &FormatSyftJSON{}
|
||||
ft = setAllToNonZero(t, ft).(*FormatSyftJSON)
|
||||
|
||||
subject := ft.buildConfig()
|
||||
assertExpectedValue(t, subject)
|
||||
}
|
||||
+11
-105
@@ -46,6 +46,17 @@ func DefaultOutput() Output {
|
||||
}
|
||||
}
|
||||
|
||||
func (o *Output) PostLoad() error {
|
||||
var errs error
|
||||
for _, loader := range []clio.PostLoader{&o.OutputFile, &o.Format} {
|
||||
if err := loader.PostLoad(); err != nil {
|
||||
errs = multierror.Append(errs, err)
|
||||
}
|
||||
}
|
||||
|
||||
return errs
|
||||
}
|
||||
|
||||
func (o *Output) AddFlags(flags clio.FlagSet) {
|
||||
var names []string
|
||||
for _, id := range supportedIDs() {
|
||||
@@ -88,111 +99,6 @@ func (o Output) OutputNameSet() *strset.Set {
|
||||
return names
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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 cycloneDxXMLEncoders() ([]sbom.FormatEncoder, error) {
|
||||
var (
|
||||
encs []sbom.FormatEncoder
|
||||
errs error
|
||||
)
|
||||
for _, v := range cyclonedxxml.SupportedVersions() {
|
||||
enc, err := cyclonedxxml.NewFormatEncoderWithConfig(cyclonedxxml.EncoderConfig{Version: v})
|
||||
if err != nil {
|
||||
errs = multierror.Append(errs, err)
|
||||
} else {
|
||||
encs = append(encs, enc)
|
||||
}
|
||||
}
|
||||
return encs, errs
|
||||
}
|
||||
|
||||
// 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 cycloneDxJSONEncoders() ([]sbom.FormatEncoder, error) {
|
||||
var (
|
||||
encs []sbom.FormatEncoder
|
||||
errs error
|
||||
)
|
||||
for _, v := range cyclonedxjson.SupportedVersions() {
|
||||
enc, err := cyclonedxjson.NewFormatEncoderWithConfig(cyclonedxjson.EncoderConfig{Version: v})
|
||||
if err != nil {
|
||||
errs = multierror.Append(errs, err)
|
||||
} else {
|
||||
encs = append(encs, enc)
|
||||
}
|
||||
}
|
||||
return encs, errs
|
||||
}
|
||||
|
||||
// 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 spdxJSONEncoders() ([]sbom.FormatEncoder, error) {
|
||||
var (
|
||||
encs []sbom.FormatEncoder
|
||||
errs error
|
||||
)
|
||||
for _, v := range spdxjson.SupportedVersions() {
|
||||
enc, err := spdxjson.NewFormatEncoderWithConfig(spdxjson.EncoderConfig{Version: v})
|
||||
if err != nil {
|
||||
errs = multierror.Append(errs, err)
|
||||
} else {
|
||||
encs = append(encs, enc)
|
||||
}
|
||||
}
|
||||
return encs, errs
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
func supportedIDs() []sbom.FormatID {
|
||||
encs := []sbom.FormatID{
|
||||
// encoders that support a single version
|
||||
|
||||
@@ -27,6 +27,7 @@ func Test_getEncoders(t *testing.T) {
|
||||
}
|
||||
|
||||
opts := DefaultOutput()
|
||||
require.NoError(t, opts.Format.PostLoad())
|
||||
opts.Format.Template.Path = "somewhere"
|
||||
|
||||
encoders, err := opts.Encoders()
|
||||
@@ -158,6 +159,7 @@ func Test_EncoderCollection_ByString_IDOnly_Defaults(t *testing.T) {
|
||||
}
|
||||
|
||||
opts := DefaultOutput()
|
||||
require.NoError(t, opts.Format.PostLoad())
|
||||
opts.Format.Template.Path = "somewhere"
|
||||
|
||||
defaultEncoders, err := opts.Encoders()
|
||||
|
||||
@@ -41,6 +41,7 @@ func Test_MakeSBOMWriter(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
opt := DefaultOutput()
|
||||
require.NoError(t, opt.Format.PostLoad())
|
||||
encoders, err := opt.Encoders()
|
||||
require.NoError(t, err)
|
||||
_, err = makeSBOMWriter(tt.outputs, "", encoders)
|
||||
|
||||
Reference in New Issue
Block a user