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