mirror of
https://github.com/gocsaf/csaf.git
synced 2025-12-22 05:40:11 +01:00
Add example for iterating product id and product helper (#617)
* Add example for iterating product id and product helper * simplify code a bit * Remove newline --------- Co-authored-by: Sascha L. Teichmann <sascha.teichmann@intevation.de>
This commit is contained in:
parent
20fdffa5cc
commit
e91bdec201
1 changed files with 141 additions and 0 deletions
141
examples/product_lister/main.go
Normal file
141
examples/product_lister/main.go
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
// Package main implements a simple demo program to
|
||||
// work with the csaf library.
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/gocsaf/csaf/v3/csaf"
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.Usage = func() {
|
||||
if _, err := fmt.Fprintf(flag.CommandLine.Output(),
|
||||
"Usage:\n %s [OPTIONS] files...\n\nOptions:\n", os.Args[0]); err != nil {
|
||||
log.Fatalf("error: %v\n", err)
|
||||
}
|
||||
flag.PrintDefaults()
|
||||
}
|
||||
printProductIdentHelper := flag.Bool("print_ident_helper", false, "print product helper mapping")
|
||||
flag.Parse()
|
||||
|
||||
files := flag.Args()
|
||||
if len(files) == 0 {
|
||||
log.Println("No files given.")
|
||||
return
|
||||
}
|
||||
|
||||
var printer func(*csaf.Advisory) error
|
||||
if *printProductIdentHelper {
|
||||
printer = printProductIdentHelperMapping
|
||||
} else {
|
||||
printer = printProductIDMapping
|
||||
}
|
||||
|
||||
if err := run(files, printer); err != nil {
|
||||
log.Fatalf("error: %v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
// visitFullProductNames iterates all full product names in the advisory.
|
||||
func visitFullProductNames(
|
||||
adv *csaf.Advisory,
|
||||
visit func(*csaf.FullProductName),
|
||||
) {
|
||||
// Iterate over all full product names
|
||||
if fpns := adv.ProductTree.FullProductNames; fpns != nil {
|
||||
for _, fpn := range *fpns {
|
||||
if fpn != nil && fpn.ProductID != nil {
|
||||
visit(fpn)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Iterate over branches recursively
|
||||
var recBranch func(b *csaf.Branch)
|
||||
recBranch = func(b *csaf.Branch) {
|
||||
if b == nil {
|
||||
return
|
||||
}
|
||||
if fpn := b.Product; fpn != nil && fpn.ProductID != nil {
|
||||
visit(fpn)
|
||||
|
||||
}
|
||||
for _, c := range b.Branches {
|
||||
recBranch(c)
|
||||
}
|
||||
}
|
||||
for _, b := range adv.ProductTree.Branches {
|
||||
recBranch(b)
|
||||
}
|
||||
|
||||
// Iterate over relationships
|
||||
if rels := adv.ProductTree.RelationShips; rels != nil {
|
||||
for _, rel := range *rels {
|
||||
if rel != nil {
|
||||
if fpn := rel.FullProductName; fpn != nil && fpn.ProductID != nil {
|
||||
visit(fpn)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// run applies fn to all loaded advisories.
|
||||
func run(files []string, fn func(*csaf.Advisory) error) error {
|
||||
for _, file := range files {
|
||||
adv, err := csaf.LoadAdvisory(file)
|
||||
if err != nil {
|
||||
return fmt.Errorf("loading %q failed: %w", file, err)
|
||||
}
|
||||
if err := fn(adv); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// printJSON serializes v as indented JSON to stdout.
|
||||
func printJSON(v any) error {
|
||||
enc := json.NewEncoder(os.Stdout)
|
||||
enc.SetIndent("", " ")
|
||||
return enc.Encode(v)
|
||||
}
|
||||
|
||||
// printProductIDMapping prints all product ids with their name and identification helper.
|
||||
func printProductIDMapping(adv *csaf.Advisory) error {
|
||||
type productNameHelperMapping struct {
|
||||
FullProductName *csaf.FullProductName `json:"product"`
|
||||
ProductIdentificationHelper *csaf.ProductIdentificationHelper `json:"product_identification_helper"`
|
||||
}
|
||||
|
||||
productIDMap := map[csaf.ProductID][]productNameHelperMapping{}
|
||||
visitFullProductNames(adv, func(fpn *csaf.FullProductName) {
|
||||
productIDMap[*fpn.ProductID] = append(productIDMap[*fpn.ProductID], productNameHelperMapping{
|
||||
FullProductName: fpn,
|
||||
ProductIdentificationHelper: fpn.ProductIdentificationHelper,
|
||||
})
|
||||
})
|
||||
return printJSON(productIDMap)
|
||||
}
|
||||
|
||||
// printProductIdentHelperMapping prints all product identifier helper with their product id.
|
||||
func printProductIdentHelperMapping(adv *csaf.Advisory) error {
|
||||
type productIdentIDMapping struct {
|
||||
ProductNameHelperMapping csaf.ProductIdentificationHelper `json:"product_identification_helper"`
|
||||
ProductID *csaf.ProductID `json:"product_id"`
|
||||
}
|
||||
|
||||
productIdentMap := []productIdentIDMapping{}
|
||||
visitFullProductNames(adv, func(fpn *csaf.FullProductName) {
|
||||
productIdentMap = append(productIdentMap, productIdentIDMapping{
|
||||
ProductNameHelperMapping: *fpn.ProductIdentificationHelper,
|
||||
ProductID: fpn.ProductID,
|
||||
})
|
||||
})
|
||||
return printJSON(productIdentMap)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue