github.com/google/osv-scalibr@v0.4.1/extractor/standalone/standalone.go (about) 1 // Copyright 2025 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Package standalone provides a way to extract in a standalone mode (e.g. a command). 16 package standalone 17 18 import ( 19 "context" 20 "path/filepath" 21 22 "github.com/google/osv-scalibr/extractor" 23 scalibrfs "github.com/google/osv-scalibr/fs" 24 "github.com/google/osv-scalibr/inventory" 25 "github.com/google/osv-scalibr/plugin" 26 ) 27 28 // Extractor is an interface for plugins that extract information independently. For 29 // example, a plugin that executes a command or retrieves information from only one file. 30 type Extractor interface { 31 extractor.Extractor 32 // Extract the information. 33 Extract(ctx context.Context, input *ScanInput) (inventory.Inventory, error) 34 } 35 36 // Config for running standalone extractors. 37 type Config struct { 38 Extractors []Extractor 39 ScanRoot *scalibrfs.ScanRoot 40 } 41 42 // ScanInput provides information for the extractor about the scan. 43 type ScanInput struct { 44 // The root of the artifact being scanned. 45 ScanRoot *scalibrfs.ScanRoot 46 } 47 48 // Run the extractors that are specified in the config. 49 func Run(ctx context.Context, config *Config) (inventory.Inventory, []*plugin.Status, error) { 50 var statuses []*plugin.Status 51 52 if !config.ScanRoot.IsVirtual() { 53 p, err := filepath.Abs(config.ScanRoot.Path) 54 if err != nil { 55 return inventory.Inventory{}, nil, err 56 } 57 config.ScanRoot.Path = p 58 } 59 60 scanInput := &ScanInput{ 61 ScanRoot: config.ScanRoot, 62 } 63 64 inv := inventory.Inventory{} 65 for _, extractor := range config.Extractors { 66 if ctx.Err() != nil { 67 return inventory.Inventory{}, nil, ctx.Err() 68 } 69 70 exInv, err := extractor.Extract(ctx, scanInput) 71 if err != nil { 72 statuses = append(statuses, plugin.StatusFromErr(extractor, false, err, nil)) 73 continue 74 } 75 for _, p := range exInv.Packages { 76 p.Plugins = append(p.Plugins, extractor.Name()) 77 } 78 79 inv.Append(exInv) 80 statuses = append(statuses, plugin.StatusFromErr(extractor, false, nil, nil)) 81 } 82 83 return inv, statuses, nil 84 }