github.com/quay/claircore@v1.5.28/indexer/ecosystem.go (about) 1 package indexer 2 3 import ( 4 "context" 5 6 "github.com/quay/zlog" 7 ) 8 9 // Ecosystems group together scanners and a Coalescer which are commonly used 10 // together. 11 // 12 // A typical ecosystem is "dpkg" which will use the "dpkg" package indexer, the 13 // "os-release" distribution scanner and the "apt" repository scanner. 14 // 15 // A Controller will scan layers with all scanners present in its configured 16 // ecosystems. 17 type Ecosystem struct { 18 PackageScanners func(ctx context.Context) ([]PackageScanner, error) 19 DistributionScanners func(ctx context.Context) ([]DistributionScanner, error) 20 RepositoryScanners func(ctx context.Context) ([]RepositoryScanner, error) 21 FileScanners func(ctx context.Context) ([]FileScanner, error) 22 Coalescer func(ctx context.Context) (Coalescer, error) 23 Name string 24 } 25 26 // EcosystemsToScanners extracts and dedupes multiple ecosystems and returns 27 // their discrete scanners. 28 func EcosystemsToScanners(ctx context.Context, ecosystems []*Ecosystem) ([]PackageScanner, []DistributionScanner, []RepositoryScanner, []FileScanner, error) { 29 ctx = zlog.ContextWithValues(ctx, "component", "indexer/EcosystemsToScanners") 30 ps := []PackageScanner{} 31 ds := []DistributionScanner{} 32 rs := []RepositoryScanner{} 33 fis := []FileScanner{} 34 seen := struct{ pkg, dist, repo, file map[string]struct{} }{ 35 make(map[string]struct{}), 36 make(map[string]struct{}), 37 make(map[string]struct{}), 38 make(map[string]struct{}), 39 } 40 41 for _, ecosystem := range ecosystems { 42 pscanners, err := ecosystem.PackageScanners(ctx) 43 if err != nil { 44 return nil, nil, nil, nil, err 45 } 46 for _, s := range pscanners { 47 n := s.Name() 48 if _, ok := seen.pkg[n]; ok { 49 continue 50 } 51 seen.pkg[n] = struct{}{} 52 ps = append(ps, s) 53 } 54 55 dscanners, err := ecosystem.DistributionScanners(ctx) 56 if err != nil { 57 return nil, nil, nil, nil, err 58 } 59 for _, s := range dscanners { 60 n := s.Name() 61 if _, ok := seen.dist[n]; ok { 62 continue 63 } 64 seen.dist[n] = struct{}{} 65 ds = append(ds, s) 66 } 67 68 rscanners, err := ecosystem.RepositoryScanners(ctx) 69 if err != nil { 70 return nil, nil, nil, nil, err 71 } 72 for _, s := range rscanners { 73 n := s.Name() 74 if _, ok := seen.repo[n]; ok { 75 continue 76 } 77 seen.repo[n] = struct{}{} 78 rs = append(rs, s) 79 } 80 81 if ecosystem.FileScanners != nil { 82 fscanners, err := ecosystem.FileScanners(ctx) 83 if err != nil { 84 return nil, nil, nil, nil, err 85 } 86 for _, s := range fscanners { 87 n := s.Name() 88 if _, ok := seen.file[n]; ok { 89 continue 90 } 91 seen.file[n] = struct{}{} 92 fis = append(fis, s) 93 } 94 } 95 } 96 return ps, ds, rs, fis, nil 97 }