github.com/anchore/syft@v1.38.2/syft/format/encoders.go (about) 1 package format 2 3 import ( 4 "fmt" 5 6 "github.com/hashicorp/go-multierror" 7 8 "github.com/anchore/syft/syft/format/cyclonedxjson" 9 "github.com/anchore/syft/syft/format/cyclonedxxml" 10 "github.com/anchore/syft/syft/format/github" 11 "github.com/anchore/syft/syft/format/purls" 12 "github.com/anchore/syft/syft/format/spdxjson" 13 "github.com/anchore/syft/syft/format/spdxtagvalue" 14 "github.com/anchore/syft/syft/format/syftjson" 15 "github.com/anchore/syft/syft/format/table" 16 "github.com/anchore/syft/syft/format/template" 17 "github.com/anchore/syft/syft/format/text" 18 "github.com/anchore/syft/syft/sbom" 19 ) 20 21 const AllVersions = "all-versions" 22 23 type EncodersConfig struct { 24 Template template.EncoderConfig 25 SyftJSON syftjson.EncoderConfig 26 SPDXJSON spdxjson.EncoderConfig 27 SPDXTagValue spdxtagvalue.EncoderConfig 28 CyclonedxJSON cyclonedxjson.EncoderConfig 29 CyclonedxXML cyclonedxxml.EncoderConfig 30 } 31 32 func Encoders() []sbom.FormatEncoder { 33 encs, _ := DefaultEncodersConfig().Encoders() 34 return encs 35 } 36 37 func DefaultEncodersConfig() EncodersConfig { 38 cfg := EncodersConfig{ 39 Template: template.DefaultEncoderConfig(), 40 SyftJSON: syftjson.DefaultEncoderConfig(), 41 SPDXJSON: spdxjson.DefaultEncoderConfig(), 42 SPDXTagValue: spdxtagvalue.DefaultEncoderConfig(), 43 CyclonedxJSON: cyclonedxjson.DefaultEncoderConfig(), 44 CyclonedxXML: cyclonedxxml.DefaultEncoderConfig(), 45 } 46 47 // empty value means to support all versions 48 cfg.SPDXJSON.Version = AllVersions 49 cfg.SPDXTagValue.Version = AllVersions 50 cfg.CyclonedxJSON.Version = AllVersions 51 cfg.CyclonedxXML.Version = AllVersions 52 53 return cfg 54 } 55 56 func (o EncodersConfig) Encoders() ([]sbom.FormatEncoder, error) { 57 var l encodersList 58 59 if o.Template.TemplatePath != "" { 60 l.addWithErr(template.ID)(o.templateEncoders()) 61 } 62 63 l.addWithErr(syftjson.ID)(o.syftJSONEncoders()) 64 l.add(table.ID)(table.NewFormatEncoder()) 65 l.add(text.ID)(text.NewFormatEncoder()) 66 l.add(purls.ID)(purls.NewFormatEncoder()) 67 l.add(github.ID)(github.NewFormatEncoder()) 68 l.addWithErr(cyclonedxxml.ID)(o.cyclonedxXMLEncoders()) 69 l.addWithErr(cyclonedxjson.ID)(o.cyclonedxJSONEncoders()) 70 l.addWithErr(spdxjson.ID)(o.spdxJSONEncoders()) 71 l.addWithErr(spdxtagvalue.ID)(o.spdxTagValueEncoders()) 72 73 return l.encoders, l.err 74 } 75 76 func (o EncodersConfig) templateEncoders() ([]sbom.FormatEncoder, error) { 77 enc, err := template.NewFormatEncoder(o.Template) 78 return []sbom.FormatEncoder{enc}, err 79 } 80 81 func (o EncodersConfig) syftJSONEncoders() ([]sbom.FormatEncoder, error) { 82 enc, err := syftjson.NewFormatEncoderWithConfig(o.SyftJSON) 83 return []sbom.FormatEncoder{enc}, err 84 } 85 86 func (o EncodersConfig) cyclonedxXMLEncoders() ([]sbom.FormatEncoder, error) { 87 var ( 88 encs []sbom.FormatEncoder 89 errs error 90 ) 91 92 cfg := o.CyclonedxXML 93 94 var versions []string 95 if cfg.Version == AllVersions { 96 versions = cyclonedxxml.SupportedVersions() 97 } else { 98 versions = []string{cfg.Version} 99 } 100 101 for _, v := range versions { 102 cfg.Version = v 103 enc, err := cyclonedxxml.NewFormatEncoderWithConfig(cfg) 104 if err != nil { 105 errs = multierror.Append(errs, err) 106 } else { 107 encs = append(encs, enc) 108 } 109 } 110 return encs, errs 111 } 112 113 func (o EncodersConfig) cyclonedxJSONEncoders() ([]sbom.FormatEncoder, error) { 114 var ( 115 encs []sbom.FormatEncoder 116 errs error 117 ) 118 119 cfg := o.CyclonedxJSON 120 121 var versions []string 122 if cfg.Version == AllVersions { 123 versions = cyclonedxjson.SupportedVersions() 124 } else { 125 versions = []string{cfg.Version} 126 } 127 128 for _, v := range versions { 129 cfg.Version = v 130 enc, err := cyclonedxjson.NewFormatEncoderWithConfig(cfg) 131 if err != nil { 132 errs = multierror.Append(errs, err) 133 } else { 134 encs = append(encs, enc) 135 } 136 } 137 return encs, errs 138 } 139 140 func (o EncodersConfig) spdxJSONEncoders() ([]sbom.FormatEncoder, error) { 141 var ( 142 encs []sbom.FormatEncoder 143 errs error 144 ) 145 146 cfg := o.SPDXJSON 147 148 var versions []string 149 if cfg.Version == AllVersions { 150 versions = spdxjson.SupportedVersions() 151 } else { 152 versions = []string{cfg.Version} 153 } 154 155 for _, v := range versions { 156 cfg.Version = v 157 enc, err := spdxjson.NewFormatEncoderWithConfig(cfg) 158 if err != nil { 159 errs = multierror.Append(errs, err) 160 } else { 161 encs = append(encs, enc) 162 } 163 } 164 return encs, errs 165 } 166 167 func (o EncodersConfig) spdxTagValueEncoders() ([]sbom.FormatEncoder, error) { 168 var ( 169 encs []sbom.FormatEncoder 170 errs error 171 ) 172 173 cfg := o.SPDXTagValue 174 175 var versions []string 176 if cfg.Version == AllVersions { 177 versions = spdxtagvalue.SupportedVersions() 178 } else { 179 versions = []string{cfg.Version} 180 } 181 182 for _, v := range versions { 183 cfg.Version = v 184 enc, err := spdxtagvalue.NewFormatEncoderWithConfig(cfg) 185 if err != nil { 186 errs = multierror.Append(errs, err) 187 } else { 188 encs = append(encs, enc) 189 } 190 } 191 return encs, errs 192 } 193 194 type encodersList struct { 195 encoders []sbom.FormatEncoder 196 err error 197 } 198 199 func (l *encodersList) addWithErr(name sbom.FormatID) func([]sbom.FormatEncoder, error) { 200 return func(encs []sbom.FormatEncoder, err error) { 201 if err != nil { 202 l.err = multierror.Append(l.err, fmt.Errorf("unable to configure %q format encoder: %w", name, err)) 203 return 204 } 205 for _, enc := range encs { 206 if enc == nil { 207 l.err = multierror.Append(l.err, fmt.Errorf("unable to configure %q format encoder: nil encoder returned", name)) 208 continue 209 } 210 l.encoders = append(l.encoders, enc) 211 } 212 } 213 } 214 215 func (l *encodersList) add(name sbom.FormatID) func(...sbom.FormatEncoder) { 216 return func(encs ...sbom.FormatEncoder) { 217 for _, enc := range encs { 218 if enc == nil { 219 l.err = multierror.Append(l.err, fmt.Errorf("unable to configure %q format encoder: nil encoder returned", name)) 220 continue 221 } 222 l.encoders = append(l.encoders, enc) 223 } 224 } 225 }