diff --git a/artifact/image/file.go b/artifact/image/file.go index df912c55..05ee9013 100644 --- a/artifact/image/file.go +++ b/artifact/image/file.go @@ -16,7 +16,7 @@ package image import "io/fs" -// History holds the creation, modification, and deletion history of a file or inventory. Each field +// History holds the creation, modification, and deletion history of a file or package. Each field // holds an array of integers representing layer indices. type History struct { Created []int diff --git a/artifact/image/layerscanning/trace/trace.go b/artifact/image/layerscanning/trace/trace.go index f8a150b5..a2f2094b 100644 --- a/artifact/image/layerscanning/trace/trace.go +++ b/artifact/image/layerscanning/trace/trace.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -// Package trace provides functionality to trace the origin of an inventory in a container image. +// Package trace provides functionality to trace the origin of a package in a container image. package trace import ( @@ -36,8 +36,8 @@ type locationAndIndex struct { index int } -// PopulateLayerDetails populates the LayerDetails field of the inventory with the origin details -// obtained by tracing the inventory in the image. +// PopulateLayerDetails populates the LayerDetails field of the package with the origin details +// obtained by tracing the package in the image. // // It does this by looking at each consecutive pair (n, n+1) of chain layers in reverse order and // checking if a package is present in layer n+1, but not layer n. For example, consider the chain @@ -54,10 +54,10 @@ type locationAndIndex struct { // // Note that a precondition of this algorithm is that the chain layers are ordered by order of // creation. -func PopulateLayerDetails(ctx context.Context, inventory []*extractor.Inventory, chainLayers []scalibrImage.ChainLayer, config *filesystem.Config) { +func PopulateLayerDetails(ctx context.Context, pkgs []*extractor.Package, chainLayers []scalibrImage.ChainLayer, config *filesystem.Config) { chainLayerDetailsList := []*extractor.LayerDetails{} - // Create list of layer details struct to be referenced by inventory. + // Create list of layer details struct to be referenced by package. for i, chainLayer := range chainLayers { var diffID string if chainLayer.Layer().IsEmpty() { @@ -85,76 +85,76 @@ func PopulateLayerDetails(ctx context.Context, inventory []*extractor.Inventory, } } - // locationIndexToInventory is used as an inventory cache to avoid re-extracting the same - // inventory from a file multiple times. - locationIndexToInventory := map[locationAndIndex][]*extractor.Inventory{} + // locationIndexToPackage is used as a package cache to avoid re-extracting the same + // package from a file multiple times. + locationIndexToPackage := map[locationAndIndex][]*extractor.Package{} lastLayerIndex := len(chainLayers) - 1 - for _, inv := range inventory { + for _, pkg := range pkgs { layerDetails := chainLayerDetailsList[lastLayerIndex] - invExtractor, isFilesystemExtractor := inv.Extractor.(filesystem.Extractor) + pkgExtractor, isFilesystemExtractor := pkg.Extractor.(filesystem.Extractor) - // Only filesystem extractors are supported for layer scanning. Also, if the inventory has no + // Only filesystem extractors are supported for layer scanning. Also, if the package has no // locations, it cannot be traced. - isInventoryTraceable := isFilesystemExtractor && len(inv.Locations) > 0 - if !isInventoryTraceable { + isPackageTraceable := isFilesystemExtractor && len(pkg.Locations) > 0 + if !isPackageTraceable { continue } var foundOrigin bool - fileLocation := inv.Locations[0] + fileLocation := pkg.Locations[0] - // Go backwards through the chain layers and find the first layer where the inventory is not - // present. Such layer is the layer in which the inventory was introduced. If the inventory is + // Go backwards through the chain layers and find the first layer where the package is not + // present. Such layer is the layer in which the package was introduced. If the package is // present in all layers, then it means it was introduced in the first layer. for i := len(chainLayers) - 2; i >= 0; i-- { oldChainLayer := chainLayers[i] - invLocationAndIndex := locationAndIndex{ + pkgLocationAndIndex := locationAndIndex{ location: fileLocation, index: i, } - var oldInventory []*extractor.Inventory - if cachedInventory, ok := locationIndexToInventory[invLocationAndIndex]; ok { - oldInventory = cachedInventory + var oldPackages []*extractor.Package + if cachedPackage, ok := locationIndexToPackage[pkgLocationAndIndex]; ok { + oldPackages = cachedPackage } else if _, err := oldChainLayer.FS().Stat(fileLocation); errors.Is(err, fs.ErrNotExist) { // Check if file still exist in this layer, if not skip extraction. // This is both an optimization, and avoids polluting the log output with false file not found errors. - oldInventory = []*extractor.Inventory{} - } else if filesExistInLayer(oldChainLayer, inv.Locations) { + oldPackages = []*extractor.Package{} + } else if filesExistInLayer(oldChainLayer, pkg.Locations) { // Update the extractor config to use the files from the current layer. // We only take extract the first location because other locations are derived from the initial // extraction location. If other locations can no longer be determined from the first location // they should not be included here, and the trace for those packages stops here. - updateExtractorConfig([]string{fileLocation}, invExtractor, oldChainLayer.FS()) + updateExtractorConfig([]string{fileLocation}, pkgExtractor, oldChainLayer.FS()) var err error // Runs SCALIBR extraction on the file of interest in oldChainLayer. - oldInventory, _, err = filesystem.Run(ctx, config) + oldPackages, _, err = filesystem.Run(ctx, config) if err != nil { break } } else { - // If none of the files from the inventory are present in the underlying layer, then there - // will be no difference in the extracted inventory from oldChainLayer, so extraction can be - // skipped in the chain layer. This is an optimization to avoid extracting the same inventory + // If none of the files from the packages are present in the underlying layer, then there + // will be no difference in the extracted packages from oldChainLayer, so extraction can be + // skipped in the chain layer. This is an optimization to avoid extracting the same package // multiple times. continue } - // Cache the inventory for future use. - locationIndexToInventory[invLocationAndIndex] = oldInventory + // Cache the packages for future use. + locationIndexToPackage[pkgLocationAndIndex] = oldPackages foundPackage := false - for _, oldInv := range oldInventory { - if areInventoriesEqual(inv, oldInv) { + for _, oldPKG := range oldPackages { + if arePackagesEqual(pkg, oldPKG) { foundPackage = true break } } - // If the inventory is not present in the old layer, then it was introduced in layer i+1. + // If the package is not present in the old layer, then it was introduced in layer i+1. if !foundPackage { layerDetails = chainLayerDetailsList[i+1] foundOrigin = true @@ -162,35 +162,35 @@ func PopulateLayerDetails(ctx context.Context, inventory []*extractor.Inventory, } } - // If the inventory is present in every layer, then it means it was introduced in the first + // If the package is present in every layer, then it means it was introduced in the first // layer. if !foundOrigin { layerDetails = chainLayerDetailsList[0] } - inv.LayerDetails = layerDetails + pkg.LayerDetails = layerDetails } } -// areInventoriesEqual checks if two inventories are equal. It does this by comparing the PURLs and -// the locations of the inventories. -func areInventoriesEqual(inv1 *extractor.Inventory, inv2 *extractor.Inventory) bool { - if inv1.Extractor == nil || inv2.Extractor == nil { +// arePackagesEqual checks if two packages are equal. It does this by comparing the PURLs and +// the locations of the packages. +func arePackagesEqual(pkg1 *extractor.Package, pkg2 *extractor.Package) bool { + if pkg1.Extractor == nil || pkg2.Extractor == nil { return false } // Check if the PURLs are equal. - purl1 := inv1.Extractor.ToPURL(inv1) - purl2 := inv2.Extractor.ToPURL(inv2) + purl1 := pkg1.Extractor.ToPURL(pkg1) + purl2 := pkg2.Extractor.ToPURL(pkg2) if purl1.String() != purl2.String() { return false } // Check if the locations are equal. - locations1 := inv1.Locations[:] + locations1 := pkg1.Locations[:] sort.Strings(locations1) - locations2 := inv2.Locations[:] + locations2 := pkg2.Locations[:] sort.Strings(locations2) if !slices.Equal(locations1, locations2) { diff --git a/artifact/image/layerscanning/trace/trace_test.go b/artifact/image/layerscanning/trace/trace_test.go index 1f1d7bd9..8bb75083 100644 --- a/artifact/image/layerscanning/trace/trace_test.go +++ b/artifact/image/layerscanning/trace/trace_test.go @@ -142,21 +142,21 @@ func TestPopulateLayerDetails(t *testing.T) { }) tests := []struct { - name string - inventory []*extractor.Inventory - extractor filesystem.Extractor - chainLayers []image.ChainLayer - wantInventory []*extractor.Inventory + name string + pkgs []*extractor.Package + extractor filesystem.Extractor + chainLayers []image.ChainLayer + wantPackages []*extractor.Package }{ { - name: "empty inventory", - inventory: []*extractor.Inventory{}, - chainLayers: []image.ChainLayer{}, - wantInventory: []*extractor.Inventory{}, + name: "empty package", + pkgs: []*extractor.Package{}, + chainLayers: []image.ChainLayer{}, + wantPackages: []*extractor.Package{}, }, { - name: "inventory in single chain layer", - inventory: []*extractor.Inventory{ + name: "package in single chain layer", + pkgs: []*extractor.Package{ { Name: fooPackage, Locations: []string{fooFile}, @@ -172,7 +172,7 @@ func TestPopulateLayerDetails(t *testing.T) { chainLayers: []image.ChainLayer{ fakeChainLayer1, }, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: fooPackage, Locations: []string{fooFile}, @@ -198,8 +198,8 @@ func TestPopulateLayerDetails(t *testing.T) { }, }, { - name: "inventory in two chain layers - package deleted in second layer", - inventory: []*extractor.Inventory{ + name: "package in two chain layers - package deleted in second layer", + pkgs: []*extractor.Package{ { Name: "foo", Locations: []string{fooFile}, @@ -211,7 +211,7 @@ func TestPopulateLayerDetails(t *testing.T) { fakeChainLayer1, fakeChainLayer2, }, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: fooPackage, Locations: []string{fooFile}, @@ -226,8 +226,8 @@ func TestPopulateLayerDetails(t *testing.T) { }, }, { - name: "inventory in multiple chain layers - package added in third layer", - inventory: []*extractor.Inventory{ + name: "package in multiple chain layers - package added in third layer", + pkgs: []*extractor.Package{ { Name: "foo", Locations: []string{fooFile}, @@ -245,7 +245,7 @@ func TestPopulateLayerDetails(t *testing.T) { fakeChainLayer2, fakeChainLayer3, }, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: fooPackage, Locations: []string{fooFile}, @@ -271,8 +271,8 @@ func TestPopulateLayerDetails(t *testing.T) { }, }, { - name: "inventory in multiple chain layers - bar package added back in last layer", - inventory: []*extractor.Inventory{ + name: "package in multiple chain layers - bar package added back in last layer", + pkgs: []*extractor.Package{ { Name: "foo", Locations: []string{fooFile}, @@ -296,7 +296,7 @@ func TestPopulateLayerDetails(t *testing.T) { fakeChainLayer3, fakeChainLayer4, }, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: fooPackage, Locations: []string{fooFile}, @@ -341,30 +341,30 @@ func TestPopulateLayerDetails(t *testing.T) { Extractors: []filesystem.Extractor{tc.extractor}, } - PopulateLayerDetails(context.Background(), tc.inventory, tc.chainLayers, config) - if diff := cmp.Diff(tc.wantInventory, tc.inventory, cmpopts.IgnoreFields(extractor.Inventory{}, "Extractor")); diff != "" { - t.Errorf("PopulateLayerDetails(ctx, %v, %v, config) returned an unexpected diff (-want +got): %v", tc.inventory, tc.chainLayers, diff) + PopulateLayerDetails(context.Background(), tc.pkgs, tc.chainLayers, config) + if diff := cmp.Diff(tc.wantPackages, tc.pkgs, cmpopts.IgnoreFields(extractor.Package{}, "Extractor")); diff != "" { + t.Errorf("PopulateLayerDetails(ctx, %v, %v, config) returned an unexpected diff (-want +got): %v", tc.pkgs, tc.chainLayers, diff) } }) } } -func TestAreInventoriesEqual(t *testing.T) { +func TestArePackagesEqual(t *testing.T) { tests := []struct { name string - inv1 *extractor.Inventory - inv2 *extractor.Inventory + pkg1 *extractor.Package + pkg2 *extractor.Package want bool }{ { name: "nil extractor", - inv1: &extractor.Inventory{ + pkg1: &extractor.Package{ Name: "foo", Version: "1.0", Locations: []string{"foo.txt"}, Extractor: nil, }, - inv2: &extractor.Inventory{ + pkg2: &extractor.Package{ Name: "foo", Version: "1.0", Locations: []string{"foo.txt"}, @@ -373,8 +373,8 @@ func TestAreInventoriesEqual(t *testing.T) { want: false, }, { - name: "same inventory", - inv1: &extractor.Inventory{ + name: "same package", + pkg1: &extractor.Package{ Name: "foo", Version: "1.0", Locations: []string{"foo.txt"}, @@ -384,7 +384,7 @@ func TestAreInventoriesEqual(t *testing.T) { }, }), }, - inv2: &extractor.Inventory{ + pkg2: &extractor.Package{ Name: "foo", Version: "1.0", Locations: []string{"foo.txt"}, @@ -397,8 +397,8 @@ func TestAreInventoriesEqual(t *testing.T) { want: true, }, { - name: "same inventory with multiple locations", - inv1: &extractor.Inventory{ + name: "same package with multiple locations", + pkg1: &extractor.Package{ Name: "foo", Version: "1.0", Locations: []string{"foo.txt", "another-foo.txt"}, @@ -408,7 +408,7 @@ func TestAreInventoriesEqual(t *testing.T) { }, }), }, - inv2: &extractor.Inventory{ + pkg2: &extractor.Package{ Name: "foo", Version: "1.0", Locations: []string{"another-foo.txt", "foo.txt"}, @@ -422,7 +422,7 @@ func TestAreInventoriesEqual(t *testing.T) { }, { name: "different name", - inv1: &extractor.Inventory{ + pkg1: &extractor.Package{ Name: "foo", Locations: []string{"foo.txt"}, Extractor: fakeextractor.New("fake-extractor", 1, []string{"foo.txt"}, map[string]fakeextractor.NamesErr{ @@ -431,7 +431,7 @@ func TestAreInventoriesEqual(t *testing.T) { }, }), }, - inv2: &extractor.Inventory{ + pkg2: &extractor.Package{ Name: "bar", Locations: []string{"foo.txt"}, Extractor: fakeextractor.New("fake-extractor", 1, []string{"foo.txt"}, map[string]fakeextractor.NamesErr{ @@ -444,7 +444,7 @@ func TestAreInventoriesEqual(t *testing.T) { }, { name: "different version", - inv1: &extractor.Inventory{ + pkg1: &extractor.Package{ Name: "foo", Version: "1.0", Locations: []string{"foo.txt"}, @@ -454,7 +454,7 @@ func TestAreInventoriesEqual(t *testing.T) { }, }), }, - inv2: &extractor.Inventory{ + pkg2: &extractor.Package{ Name: "foo", Version: "2.0", Locations: []string{"foo.txt"}, @@ -468,7 +468,7 @@ func TestAreInventoriesEqual(t *testing.T) { }, { name: "different locations", - inv1: &extractor.Inventory{ + pkg1: &extractor.Package{ Name: "foo", Locations: []string{"foo.txt"}, Extractor: fakeextractor.New("fake-extractor", 1, []string{"foo.txt"}, map[string]fakeextractor.NamesErr{ @@ -477,7 +477,7 @@ func TestAreInventoriesEqual(t *testing.T) { }, }), }, - inv2: &extractor.Inventory{ + pkg2: &extractor.Package{ Name: "foo", Locations: []string{"another-foo.txt"}, Extractor: fakeextractor.New("fake-extractor", 1, []string{"foo.txt"}, map[string]fakeextractor.NamesErr{ @@ -491,8 +491,8 @@ func TestAreInventoriesEqual(t *testing.T) { } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { - if got := areInventoriesEqual(tc.inv1, tc.inv2); got != tc.want { - t.Errorf("areInventoriesEqual(%v, %v) = %v, want: %v", tc.inv1, tc.inv2, got, tc.want) + if got := arePackagesEqual(tc.pkg1, tc.pkg2); got != tc.want { + t.Errorf("arePackagesEqual(%v, %v) = %v, want: %v", tc.pkg1, tc.pkg2, got, tc.want) } }) } diff --git a/binary/cli/cli_test.go b/binary/cli/cli_test.go index e41e7147..45bb5702 100644 --- a/binary/cli/cli_test.go +++ b/binary/cli/cli_test.go @@ -476,8 +476,9 @@ func TestGetScanConfig_GovulncheckParams(t *testing.T) { func TestWriteScanResults(t *testing.T) { testDirPath := t.TempDir() result := &scalibr.ScanResult{ - Version: "1.2.3", - Status: &plugin.ScanStatus{Status: plugin.ScanStatusSucceeded}, + Version: "1.2.3", + Status: &plugin.ScanStatus{Status: plugin.ScanStatusSucceeded}, + Inventory: &scalibr.Inventory{}, } for _, tc := range []struct { desc string diff --git a/binary/proto/proto.go b/binary/proto/proto.go index 5354b9ed..be457a93 100644 --- a/binary/proto/proto.go +++ b/binary/proto/proto.go @@ -164,17 +164,17 @@ func ScanResultToProto(r *scalibr.ScanResult) (*spb.ScanResult, error) { pluginStatus = append(pluginStatus, pluginStatusToProto(s)) } - inventories := make([]*spb.Inventory, 0, len(r.Inventories)) - for _, i := range r.Inventories { - p, err := inventoryToProto(i) + packages := make([]*spb.Package, 0, len(r.Inventory.Packages)) + for _, pkg := range r.Inventory.Packages { + p, err := packageToProto(pkg) if err != nil { return nil, err } - inventories = append(inventories, p) + packages = append(packages, p) } - findings := make([]*spb.Finding, 0, len(r.Findings)) - for _, f := range r.Findings { + findings := make([]*spb.Finding, 0, len(r.Inventory.Findings)) + for _, f := range r.Inventory.Findings { p, err := findingToProto(f) if err != nil { return nil, err @@ -188,8 +188,11 @@ func ScanResultToProto(r *scalibr.ScanResult) (*spb.ScanResult, error) { EndTime: timestamppb.New(r.EndTime), Status: scanStatusToProto(r.Status), PluginStatus: pluginStatus, - Inventories: inventories, - Findings: findings, + // TODO(b/400910349): Stop setting the deprecated fields + // once integrators no longer read them. + InventoriesDeprecated: packages, + FindingsDeprecated: findings, + Inventory: &spb.Inventory{Packages: packages, Findings: findings}, }, nil } @@ -216,37 +219,37 @@ func pluginStatusToProto(s *plugin.Status) *spb.PluginStatus { } } -func inventoryToProto(i *extractor.Inventory) (*spb.Inventory, error) { - if i == nil { +func packageToProto(pkg *extractor.Package) (*spb.Package, error) { + if pkg == nil { return nil, nil } - p := converter.ToPURL(i) - inventoryProto := &spb.Inventory{ - Name: i.Name, - Version: i.Version, - SourceCode: sourceCodeIdentifierToProto(i.SourceCode), + p := converter.ToPURL(pkg) + packageProto := &spb.Package{ + Name: pkg.Name, + Version: pkg.Version, + SourceCode: sourceCodeIdentifierToProto(pkg.SourceCode), Purl: purlToProto(p), - Ecosystem: i.Ecosystem(), - Locations: i.Locations, - Extractor: i.Extractor.Name(), - Annotations: annotationsToProto(i.Annotations), - LayerDetails: layerDetailsToProto(i.LayerDetails), - } - setProtoMetadata(i.Metadata, inventoryProto) - return inventoryProto, nil + Ecosystem: pkg.Ecosystem(), + Locations: pkg.Locations, + Extractor: pkg.Extractor.Name(), + Annotations: annotationsToProto(pkg.Annotations), + LayerDetails: layerDetailsToProto(pkg.LayerDetails), + } + setProtoMetadata(pkg.Metadata, packageProto) + return packageProto, nil } -func setProtoMetadata(meta any, i *spb.Inventory) { +func setProtoMetadata(meta any, p *spb.Package) { switch m := meta.(type) { case *wheelegg.PythonPackageMetadata: - i.Metadata = &spb.Inventory_PythonMetadata{ + p.Metadata = &spb.Package_PythonMetadata{ PythonMetadata: &spb.PythonPackageMetadata{ Author: m.Author, AuthorEmail: m.AuthorEmail, }, } case *packagejson.JavascriptPackageJSONMetadata: - i.Metadata = &spb.Inventory_JavascriptMetadata{ + p.Metadata = &spb.Package_JavascriptMetadata{ JavascriptMetadata: &spb.JavascriptPackageJSONMetadata{ Author: m.Author.PersonString(), Contributors: personsToProto(m.Contributors), @@ -254,7 +257,7 @@ func setProtoMetadata(meta any, i *spb.Inventory) { }, } case *depsjson.Metadata: - i.Metadata = &spb.Inventory_DepsjsonMetadata{ + p.Metadata = &spb.Package_DepsjsonMetadata{ DepsjsonMetadata: &spb.DEPSJSONMetadata{ PackageName: m.PackageName, PackageVersion: m.PackageVersion, @@ -262,7 +265,7 @@ func setProtoMetadata(meta any, i *spb.Inventory) { }, } case *apk.Metadata: - i.Metadata = &spb.Inventory_ApkMetadata{ + p.Metadata = &spb.Package_ApkMetadata{ ApkMetadata: &spb.APKPackageMetadata{ PackageName: m.PackageName, OriginName: m.OriginName, @@ -274,7 +277,7 @@ func setProtoMetadata(meta any, i *spb.Inventory) { }, } case *dpkg.Metadata: - i.Metadata = &spb.Inventory_DpkgMetadata{ + p.Metadata = &spb.Package_DpkgMetadata{ DpkgMetadata: &spb.DPKGPackageMetadata{ PackageName: m.PackageName, SourceName: m.SourceName, @@ -289,7 +292,7 @@ func setProtoMetadata(meta any, i *spb.Inventory) { }, } case *snap.Metadata: - i.Metadata = &spb.Inventory_SnapMetadata{ + p.Metadata = &spb.Package_SnapMetadata{ SnapMetadata: &spb.SNAPPackageMetadata{ Name: m.Name, Version: m.Version, @@ -302,7 +305,7 @@ func setProtoMetadata(meta any, i *spb.Inventory) { }, } case *rpm.Metadata: - i.Metadata = &spb.Inventory_RpmMetadata{ + p.Metadata = &spb.Package_RpmMetadata{ RpmMetadata: &spb.RPMPackageMetadata{ PackageName: m.PackageName, SourceRpm: m.SourceRPM, @@ -317,7 +320,7 @@ func setProtoMetadata(meta any, i *spb.Inventory) { }, } case *cos.Metadata: - i.Metadata = &spb.Inventory_CosMetadata{ + p.Metadata = &spb.Package_CosMetadata{ CosMetadata: &spb.COSPackageMetadata{ Name: m.Name, Version: m.Version, @@ -327,7 +330,7 @@ func setProtoMetadata(meta any, i *spb.Inventory) { }, } case *pacman.Metadata: - i.Metadata = &spb.Inventory_PacmanMetadata{ + p.Metadata = &spb.Package_PacmanMetadata{ PacmanMetadata: &spb.PACMANPackageMetadata{ PackageName: m.PackageName, PackageVersion: m.PackageVersion, @@ -337,7 +340,7 @@ func setProtoMetadata(meta any, i *spb.Inventory) { }, } case *portage.Metadata: - i.Metadata = &spb.Inventory_PortageMetadata{ + p.Metadata = &spb.Package_PortageMetadata{ PortageMetadata: &spb.PortagePackageMetadata{ PackageName: m.PackageName, PackageVersion: m.PackageVersion, @@ -346,7 +349,7 @@ func setProtoMetadata(meta any, i *spb.Inventory) { }, } case *flatpak.Metadata: - i.Metadata = &spb.Inventory_FlatpakMetadata{ + p.Metadata = &spb.Package_FlatpakMetadata{ FlatpakMetadata: &spb.FlatpakPackageMetadata{ PackageName: m.PackageName, PackageId: m.PackageID, @@ -360,7 +363,7 @@ func setProtoMetadata(meta any, i *spb.Inventory) { }, } case *nix.Metadata: - i.Metadata = &spb.Inventory_NixMetadata{ + p.Metadata = &spb.Package_NixMetadata{ NixMetadata: &spb.NixPackageMetadata{ PackageName: m.PackageName, PackageVersion: m.PackageVersion, @@ -372,7 +375,7 @@ func setProtoMetadata(meta any, i *spb.Inventory) { }, } case *macapps.Metadata: - i.Metadata = &spb.Inventory_MacAppsMetadata{ + p.Metadata = &spb.Package_MacAppsMetadata{ MacAppsMetadata: &spb.MacAppsMetadata{ BundleDisplayName: m.CFBundleDisplayName, BundleIdentifier: m.CFBundleIdentifier, @@ -387,11 +390,11 @@ func setProtoMetadata(meta any, i *spb.Inventory) { }, } case *homebrew.Metadata: - i.Metadata = &spb.Inventory_HomebrewMetadata{ + p.Metadata = &spb.Package_HomebrewMetadata{ HomebrewMetadata: &spb.HomebrewPackageMetadata{}, } case *module.Metadata: - i.Metadata = &spb.Inventory_KernelModuleMetadata{ + p.Metadata = &spb.Package_KernelModuleMetadata{ KernelModuleMetadata: &spb.KernelModuleMetadata{ PackageName: m.PackageName, PackageVersion: m.PackageVersion, @@ -403,7 +406,7 @@ func setProtoMetadata(meta any, i *spb.Inventory) { PackageAuthor: m.PackageAuthor}, } case *vmlinuz.Metadata: - i.Metadata = &spb.Inventory_VmlinuzMetadata{ + p.Metadata = &spb.Package_VmlinuzMetadata{ VmlinuzMetadata: &spb.VmlinuzMetadata{ Name: m.Name, Version: m.Version, @@ -420,7 +423,7 @@ func setProtoMetadata(meta any, i *spb.Inventory) { }, } case *ctrdfs.Metadata: - i.Metadata = &spb.Inventory_ContainerdContainerMetadata{ + p.Metadata = &spb.Package_ContainerdContainerMetadata{ ContainerdContainerMetadata: &spb.ContainerdContainerMetadata{ NamespaceName: m.Namespace, ImageName: m.ImageName, @@ -437,7 +440,7 @@ func setProtoMetadata(meta any, i *spb.Inventory) { }, } case *ctrdruntime.Metadata: - i.Metadata = &spb.Inventory_ContainerdRuntimeContainerMetadata{ + p.Metadata = &spb.Package_ContainerdRuntimeContainerMetadata{ ContainerdRuntimeContainerMetadata: &spb.ContainerdRuntimeContainerMetadata{ NamespaceName: m.Namespace, ImageName: m.ImageName, @@ -449,21 +452,21 @@ func setProtoMetadata(meta any, i *spb.Inventory) { }, } case *spdx.Metadata: - i.Metadata = &spb.Inventory_SpdxMetadata{ + p.Metadata = &spb.Package_SpdxMetadata{ SpdxMetadata: &spb.SPDXPackageMetadata{ Purl: purlToProto(m.PURL), Cpes: m.CPEs, }, } case *cdx.Metadata: - i.Metadata = &spb.Inventory_CdxMetadata{ + p.Metadata = &spb.Package_CdxMetadata{ CdxMetadata: &spb.CDXPackageMetadata{ Purl: purlToProto(m.PURL), Cpes: m.CPEs, }, } case *archive.Metadata: - i.Metadata = &spb.Inventory_JavaArchiveMetadata{ + p.Metadata = &spb.Package_JavaArchiveMetadata{ JavaArchiveMetadata: &spb.JavaArchiveMetadata{ ArtifactId: m.ArtifactID, GroupId: m.GroupID, @@ -471,14 +474,14 @@ func setProtoMetadata(meta any, i *spb.Inventory) { }, } case *javalockfile.Metadata: - i.Metadata = &spb.Inventory_JavaLockfileMetadata{ + p.Metadata = &spb.Package_JavaLockfileMetadata{ JavaLockfileMetadata: &spb.JavaLockfileMetadata{ ArtifactId: m.ArtifactID, GroupId: m.GroupID, }, } case *osv.Metadata: - i.Metadata = &spb.Inventory_OsvMetadata{ + p.Metadata = &spb.Package_OsvMetadata{ OsvMetadata: &spb.OSVPackageMetadata{ PurlType: m.PURLType, Commit: m.Commit, @@ -487,20 +490,20 @@ func setProtoMetadata(meta any, i *spb.Inventory) { }, } case *requirements.Metadata: - i.Metadata = &spb.Inventory_PythonRequirementsMetadata{ + p.Metadata = &spb.Package_PythonRequirementsMetadata{ PythonRequirementsMetadata: &spb.PythonRequirementsMetadata{ HashCheckingModeValues: m.HashCheckingModeValues, VersionComparator: m.VersionComparator, }, } case *setup.Metadata: - i.Metadata = &spb.Inventory_PythonSetupMetadata{ + p.Metadata = &spb.Package_PythonSetupMetadata{ PythonSetupMetadata: &spb.PythonSetupMetadata{ VersionComparator: m.VersionComparator, }, } case *winmetadata.OSVersion: - i.Metadata = &spb.Inventory_WindowsOsVersionMetadata{ + p.Metadata = &spb.Package_WindowsOsVersionMetadata{ WindowsOsVersionMetadata: &spb.WindowsOSVersion{ Product: m.Product, FullVersion: m.FullVersion, @@ -532,28 +535,28 @@ func purlToProto(p *purl.PackageURL) *spb.Purl { } } -func annotationsToProto(as []extractor.Annotation) []spb.Inventory_AnnotationEnum { +func annotationsToProto(as []extractor.Annotation) []spb.Package_AnnotationEnum { if as == nil { return nil } - ps := []spb.Inventory_AnnotationEnum{} + ps := []spb.Package_AnnotationEnum{} for _, a := range as { ps = append(ps, annotationToProto(a)) } return ps } -func annotationToProto(s extractor.Annotation) spb.Inventory_AnnotationEnum { - var e spb.Inventory_AnnotationEnum +func annotationToProto(s extractor.Annotation) spb.Package_AnnotationEnum { + var e spb.Package_AnnotationEnum switch s { case extractor.Transitional: - e = spb.Inventory_TRANSITIONAL + e = spb.Package_TRANSITIONAL case extractor.InsideOSPackage: - e = spb.Inventory_INSIDE_OS_PACKAGE + e = spb.Package_INSIDE_OS_PACKAGE case extractor.InsideCacheDir: - e = spb.Inventory_INSIDE_CACHE_DIR + e = spb.Package_INSIDE_CACHE_DIR default: - e = spb.Inventory_UNSPECIFIED + e = spb.Package_UNSPECIFIED } return e } @@ -600,13 +603,13 @@ func findingToProto(f *detector.Finding) (*spb.Finding, error) { } var target *spb.TargetDetails if f.Target != nil { - i, err := inventoryToProto(f.Target.Inventory) + i, err := packageToProto(f.Target.Package) if err != nil { return nil, err } target = &spb.TargetDetails{ - Location: f.Target.Location, - Inventory: i, + Location: f.Target.Location, + Package: i, } } if f.Adv.ID == nil { diff --git a/binary/proto/proto_test.go b/binary/proto/proto_test.go index cb719008..24ddb614 100644 --- a/binary/proto/proto_test.go +++ b/binary/proto/proto_test.go @@ -160,7 +160,7 @@ func TestScanResultToProto(t *testing.T) { successProto := &spb.ScanStatus{Status: spb.ScanStatus_SUCCEEDED} failure := &plugin.ScanStatus{Status: plugin.ScanStatusFailed, FailureReason: "failure"} failureProto := &spb.ScanStatus{Status: spb.ScanStatus_FAILED, FailureReason: "failure"} - purlDPKGInventory := &extractor.Inventory{ + purlDPKGPackage := &extractor.Package{ Name: "software", Version: "1.0.0", Metadata: &dpkg.Metadata{ @@ -174,7 +174,7 @@ func TestScanResultToProto(t *testing.T) { Locations: []string{"/file1"}, Extractor: dpkg.New(dpkg.DefaultConfig()), } - purlDPKGAnnotationInventory := &extractor.Inventory{ + purlDPKGAnnotationPackage := &extractor.Package{ Name: "software", Version: "1.0.0", Metadata: &dpkg.Metadata{ @@ -189,7 +189,7 @@ func TestScanResultToProto(t *testing.T) { Extractor: dpkg.New(dpkg.DefaultConfig()), Annotations: []extractor.Annotation{extractor.Transitional}, } - purlPythonInventory := &extractor.Inventory{ + purlPythonPackage := &extractor.Package{ Name: "software", Version: "1.0.0", Locations: []string{"/file1"}, @@ -199,7 +199,7 @@ func TestScanResultToProto(t *testing.T) { AuthorEmail: "author@corp.com", }, } - pythonRequirementsInventory := &extractor.Inventory{ + pythonRequirementsPackage := &extractor.Package{ Name: "foo", Version: "1.0", Locations: []string{"/file1"}, @@ -209,7 +209,7 @@ func TestScanResultToProto(t *testing.T) { VersionComparator: ">=", }, } - purlJavascriptInventory := &extractor.Inventory{ + purlJavascriptPackage := &extractor.Package{ Name: "software", Version: "1.0.0", Metadata: &packagejson.JavascriptPackageJSONMetadata{ @@ -229,7 +229,7 @@ func TestScanResultToProto(t *testing.T) { Extractor: &packagejson.Extractor{}, } - purlDotnetDepsJSONInventory := &extractor.Inventory{ + purlDotnetDepsJSONPackage := &extractor.Package{ Name: "software", Version: "1.0.0", Metadata: &depsjson.Metadata{ @@ -241,7 +241,7 @@ func TestScanResultToProto(t *testing.T) { Extractor: &depsjson.Extractor{}, } - purlDotnetDepsJSONInventoryProto := &spb.Inventory{ + purlDotnetDepsJSONPackageProto := &spb.Package{ Name: "software", Version: "1.0.0", Purl: &spb.Purl{ @@ -253,7 +253,7 @@ func TestScanResultToProto(t *testing.T) { Ecosystem: "NuGet", Locations: []string{"/file1"}, Extractor: "dotnet/depsjson", - Metadata: &spb.Inventory_DepsjsonMetadata{ + Metadata: &spb.Package_DepsjsonMetadata{ DepsjsonMetadata: &spb.DEPSJSONMetadata{ PackageName: "software", PackageVersion: "1.0.0", @@ -262,7 +262,7 @@ func TestScanResultToProto(t *testing.T) { }, } - windowsInventory := &extractor.Inventory{ + windowsPackage := &extractor.Package{ Name: "windows_server_2019", Version: "10.0.17763.3406", Metadata: &winmetadata.OSVersion{ @@ -272,7 +272,7 @@ func TestScanResultToProto(t *testing.T) { Extractor: &dismpatch.Extractor{}, } - purlDPKGInventoryProto := &spb.Inventory{ + purlDPKGPackageProto := &spb.Package{ Name: "software", Version: "1.0.0", Purl: &spb.Purl{ @@ -287,7 +287,7 @@ func TestScanResultToProto(t *testing.T) { }, }, Ecosystem: "Debian", - Metadata: &spb.Inventory_DpkgMetadata{ + Metadata: &spb.Package_DpkgMetadata{ DpkgMetadata: &spb.DPKGPackageMetadata{ PackageName: "software", PackageVersion: "1.0.0", @@ -300,7 +300,7 @@ func TestScanResultToProto(t *testing.T) { Locations: []string{"/file1"}, Extractor: "os/dpkg", } - purlDPKGAnnotationInventoryProto := &spb.Inventory{ + purlDPKGAnnotationPackageProto := &spb.Package{ Name: "software", Version: "1.0.0", Purl: &spb.Purl{ @@ -315,7 +315,7 @@ func TestScanResultToProto(t *testing.T) { }, }, Ecosystem: "Debian", - Metadata: &spb.Inventory_DpkgMetadata{ + Metadata: &spb.Package_DpkgMetadata{ DpkgMetadata: &spb.DPKGPackageMetadata{ PackageName: "software", PackageVersion: "1.0.0", @@ -327,9 +327,9 @@ func TestScanResultToProto(t *testing.T) { }, Locations: []string{"/file1"}, Extractor: "os/dpkg", - Annotations: []spb.Inventory_AnnotationEnum{spb.Inventory_TRANSITIONAL}, + Annotations: []spb.Package_AnnotationEnum{spb.Package_TRANSITIONAL}, } - purlPythonInventoryProto := &spb.Inventory{ + purlPythonPackageProto := &spb.Package{ Name: "software", Version: "1.0.0", Purl: &spb.Purl{ @@ -341,14 +341,14 @@ func TestScanResultToProto(t *testing.T) { Ecosystem: "PyPI", Locations: []string{"/file1"}, Extractor: "python/wheelegg", - Metadata: &spb.Inventory_PythonMetadata{ + Metadata: &spb.Package_PythonMetadata{ PythonMetadata: &spb.PythonPackageMetadata{ Author: "author", AuthorEmail: "author@corp.com", }, }, } - pythonRequirementsInventoryProto := &spb.Inventory{ + pythonRequirementsPackageProto := &spb.Package{ Name: "foo", Version: "1.0", Purl: &spb.Purl{ @@ -360,14 +360,14 @@ func TestScanResultToProto(t *testing.T) { Ecosystem: "PyPI", Locations: []string{"/file1"}, Extractor: "python/requirements", - Metadata: &spb.Inventory_PythonRequirementsMetadata{ + Metadata: &spb.Package_PythonRequirementsMetadata{ PythonRequirementsMetadata: &spb.PythonRequirementsMetadata{ HashCheckingModeValues: []string{"sha256:123"}, VersionComparator: ">=", }, }, } - purlJavascriptInventoryProto := &spb.Inventory{ + purlJavascriptPackageProto := &spb.Package{ Name: "software", Version: "1.0.0", Purl: &spb.Purl{ @@ -379,7 +379,7 @@ func TestScanResultToProto(t *testing.T) { Ecosystem: "npm", Locations: []string{"/file1"}, Extractor: "javascript/packagejson", - Metadata: &spb.Inventory_JavascriptMetadata{ + Metadata: &spb.Package_JavascriptMetadata{ JavascriptMetadata: &spb.JavascriptPackageJSONMetadata{ Maintainers: []string{ "maintainer1 (https://blog.maintainer1.com)", @@ -388,7 +388,7 @@ func TestScanResultToProto(t *testing.T) { }, }, } - cdxInventory := &extractor.Inventory{ + cdxPackage := &extractor.Package{ Name: "openssl", Version: "1.1.1", Metadata: &cdx.Metadata{ @@ -401,7 +401,7 @@ func TestScanResultToProto(t *testing.T) { Locations: []string{"/openssl"}, Extractor: &cdx.Extractor{}, } - cdxInventoryProto := &spb.Inventory{ + cdxPackageProto := &spb.Package{ Name: "openssl", Version: "1.1.1", Ecosystem: "generic", @@ -411,7 +411,7 @@ func TestScanResultToProto(t *testing.T) { Name: "openssl", Version: "1.1.1", }, - Metadata: &spb.Inventory_CdxMetadata{ + Metadata: &spb.Package_CdxMetadata{ CdxMetadata: &spb.CDXPackageMetadata{ Purl: &spb.Purl{ Purl: "pkg:generic/openssl@1.1.1", @@ -424,7 +424,7 @@ func TestScanResultToProto(t *testing.T) { Locations: []string{"/openssl"}, Extractor: "sbom/cdx", } - purlRPMInventory := &extractor.Inventory{ + purlRPMPackage := &extractor.Package{ Name: "openssh-clients", Version: "5.3p1", Metadata: &rpm.Metadata{ @@ -442,7 +442,7 @@ func TestScanResultToProto(t *testing.T) { Locations: []string{"/file1"}, Extractor: rpm.New(rpm.DefaultConfig()), } - purlRPMInventoryProto := &spb.Inventory{ + purlRPMPackageProto := &spb.Package{ Name: "openssh-clients", Version: "5.3p1", Purl: &spb.Purl{ @@ -459,7 +459,7 @@ func TestScanResultToProto(t *testing.T) { }, }, Ecosystem: "Red Hat", - Metadata: &spb.Inventory_RpmMetadata{ + Metadata: &spb.Package_RpmMetadata{ RpmMetadata: &spb.RPMPackageMetadata{ PackageName: "openssh-clients", SourceRpm: "openssh-5.3p1-124.el6_10.src.rpm", @@ -476,7 +476,7 @@ func TestScanResultToProto(t *testing.T) { Locations: []string{"/file1"}, Extractor: "os/rpm", } - purlPACMANInventory := &extractor.Inventory{ + purlPACMANPackage := &extractor.Package{ Name: "zstd", Version: "1.5.6-1", Metadata: &pacman.Metadata{ @@ -488,7 +488,7 @@ func TestScanResultToProto(t *testing.T) { Locations: []string{"/file1"}, Extractor: pacman.New(pacman.DefaultConfig()), } - purlPACMANInventoryProto := &spb.Inventory{ + purlPACMANPackageProto := &spb.Package{ Name: "zstd", Version: "1.5.6-1", Purl: &spb.Purl{ @@ -502,7 +502,7 @@ func TestScanResultToProto(t *testing.T) { }, }, Ecosystem: "Arch:20241201.0.284684", - Metadata: &spb.Inventory_PacmanMetadata{ + Metadata: &spb.Package_PacmanMetadata{ PacmanMetadata: &spb.PACMANPackageMetadata{ PackageName: "zstd", PackageVersion: "1.5.6-1", @@ -513,7 +513,7 @@ func TestScanResultToProto(t *testing.T) { Locations: []string{"/file1"}, Extractor: "os/pacman", } - purlPORTAGEInventory := &extractor.Inventory{ + purlPORTAGEPackage := &extractor.Package{ Name: "Capture-Tiny", Version: "0.480.0-r1", Metadata: &portage.Metadata{ @@ -525,7 +525,7 @@ func TestScanResultToProto(t *testing.T) { Locations: []string{"/file1"}, Extractor: portage.New(portage.DefaultConfig()), } - purlPORTAGEInventoryProto := &spb.Inventory{ + purlPORTAGEPackageProto := &spb.Package{ Name: "Capture-Tiny", Version: "0.480.0-r1", Purl: &spb.Purl{ @@ -539,7 +539,7 @@ func TestScanResultToProto(t *testing.T) { }, }, Ecosystem: "Gentoo:2.17", - Metadata: &spb.Inventory_PortageMetadata{ + Metadata: &spb.Package_PortageMetadata{ PortageMetadata: &spb.PortagePackageMetadata{ PackageName: "Capture-Tiny", PackageVersion: "0.480.0-r1", @@ -550,7 +550,7 @@ func TestScanResultToProto(t *testing.T) { Locations: []string{"/file1"}, Extractor: "os/portage", } - purlNixInventory := &extractor.Inventory{ + purlNixPackage := &extractor.Package{ Name: "attr", Version: "2.5.2", Metadata: &nix.Metadata{ @@ -563,7 +563,7 @@ func TestScanResultToProto(t *testing.T) { Locations: []string{"/file1"}, Extractor: nix.New(), } - purlNixInventoryProto := &spb.Inventory{ + purlNixPackageProto := &spb.Package{ Name: "attr", Version: "2.5.2", Purl: &spb.Purl{ @@ -576,7 +576,7 @@ func TestScanResultToProto(t *testing.T) { }, }, Ecosystem: "", - Metadata: &spb.Inventory_NixMetadata{ + Metadata: &spb.Package_NixMetadata{ NixMetadata: &spb.NixPackageMetadata{ PackageName: "attr", PackageVersion: "2.5.2", @@ -588,14 +588,14 @@ func TestScanResultToProto(t *testing.T) { Locations: []string{"/file1"}, Extractor: "os/nix", } - purlHomebrewInventory := &extractor.Inventory{ + purlHomebrewPackage := &extractor.Package{ Name: "rclone", Version: "1.67.0", Metadata: &homebrew.Metadata{}, Locations: []string{"/file1"}, Extractor: homebrew.Extractor{}, } - purlHomebrewInventoryProto := &spb.Inventory{ + purlHomebrewPackageProto := &spb.Package{ Name: "rclone", Version: "1.67.0", Purl: &spb.Purl{ @@ -604,11 +604,11 @@ func TestScanResultToProto(t *testing.T) { Name: "rclone", Version: "1.67.0", }, - Metadata: &spb.Inventory_HomebrewMetadata{}, + Metadata: &spb.Package_HomebrewMetadata{}, Locations: []string{"/file1"}, Extractor: "os/homebrew", } - containerdInventory := &extractor.Inventory{ + containerdPackage := &extractor.Package{ Name: "gcr.io/google-samples/hello-app:1.0", Version: "sha256:b1455e1c4fcc5ea1023c9e3b584cd84b64eb920e332feff690a2829696e379e7", Metadata: &ctrdfs.Metadata{ @@ -626,11 +626,11 @@ func TestScanResultToProto(t *testing.T) { Locations: []string{"/file4"}, Extractor: &ctrdfs.Extractor{}, } - containerdInventoryProto := &spb.Inventory{ + containerdPackageProto := &spb.Package{ Name: "gcr.io/google-samples/hello-app:1.0", Version: "sha256:b1455e1c4fcc5ea1023c9e3b584cd84b64eb920e332feff690a2829696e379e7", Ecosystem: "", - Metadata: &spb.Inventory_ContainerdContainerMetadata{ + Metadata: &spb.Package_ContainerdContainerMetadata{ ContainerdContainerMetadata: &spb.ContainerdContainerMetadata{ NamespaceName: "default", ImageName: "gcr.io/google-samples/hello-app:1.0", @@ -647,7 +647,7 @@ func TestScanResultToProto(t *testing.T) { Locations: []string{"/file4"}, Extractor: "containers/containerd", } - containerdRuntimeInventory := &extractor.Inventory{ + containerdRuntimePackage := &extractor.Package{ Name: "gcr.io/google-samples/hello-app:1.0", Version: "sha256:b1455e1c4fcc5ea1023c9e3b584cd84b64eb920e332feff690a2829696e379e7", Metadata: &ctrdruntime.Metadata{ @@ -662,11 +662,11 @@ func TestScanResultToProto(t *testing.T) { Locations: []string{"/file7"}, Extractor: &ctrdruntime.Extractor{}, } - containerdRuntimeInventoryProto := &spb.Inventory{ + containerdRuntimePackageProto := &spb.Package{ Name: "gcr.io/google-samples/hello-app:1.0", Version: "sha256:b1455e1c4fcc5ea1023c9e3b584cd84b64eb920e332feff690a2829696e379e7", Ecosystem: "", - Metadata: &spb.Inventory_ContainerdRuntimeContainerMetadata{ + Metadata: &spb.Package_ContainerdRuntimeContainerMetadata{ ContainerdRuntimeContainerMetadata: &spb.ContainerdRuntimeContainerMetadata{ NamespaceName: "default", ImageName: "gcr.io/google-samples/hello-app:1.0", @@ -680,10 +680,10 @@ func TestScanResultToProto(t *testing.T) { Locations: []string{"/file7"}, Extractor: "containers/containerd-runtime", } - windowsInventoryProto := &spb.Inventory{ + windowsPackageProto := &spb.Package{ Name: "windows_server_2019", Version: "10.0.17763.3406", - Metadata: &spb.Inventory_WindowsOsVersionMetadata{ + Metadata: &spb.Package_WindowsOsVersionMetadata{ WindowsOsVersionMetadata: &spb.WindowsOSVersion{ Product: "windows_server_2019", FullVersion: "10.0.17763.3406", @@ -703,7 +703,7 @@ func TestScanResultToProto(t *testing.T) { }, Extractor: "windows/dismpatch", } - purlPythonInventoryWithLayerDetails := &extractor.Inventory{ + purlPythonPackageWithLayerDetails := &extractor.Package{ Name: "software", Version: "1.0.0", Locations: []string{"/file1"}, @@ -719,7 +719,7 @@ func TestScanResultToProto(t *testing.T) { InBaseImage: true, }, } - purlPythonInventoryWithLayerDetailsProto := &spb.Inventory{ + purlPythonPackageWithLayerDetailsProto := &spb.Package{ Name: "software", Version: "1.0.0", Purl: &spb.Purl{ @@ -731,7 +731,7 @@ func TestScanResultToProto(t *testing.T) { Ecosystem: "PyPI", Locations: []string{"/file1"}, Extractor: "python/wheelegg", - Metadata: &spb.Inventory_PythonMetadata{ + Metadata: &spb.Package_PythonMetadata{ PythonMetadata: &spb.PythonPackageMetadata{ Author: "author", AuthorEmail: "author@corp.com", @@ -771,40 +771,42 @@ func TestScanResultToProto(t *testing.T) { Status: success, }, }, - Inventories: []*extractor.Inventory{ - purlDPKGInventory, - purlDPKGAnnotationInventory, - purlPythonInventory, - pythonRequirementsInventory, - purlJavascriptInventory, - purlDotnetDepsJSONInventory, - cdxInventory, - windowsInventory, - purlPythonInventoryWithLayerDetails, - purlHomebrewInventory, - }, - Findings: []*detector.Finding{ - { - Adv: &detector.Advisory{ - ID: &detector.AdvisoryID{ - Publisher: "CVE", - Reference: "CVE-1234", + Inventory: &scalibr.Inventory{ + Packages: []*extractor.Package{ + purlDPKGPackage, + purlDPKGAnnotationPackage, + purlPythonPackage, + pythonRequirementsPackage, + purlJavascriptPackage, + purlDotnetDepsJSONPackage, + cdxPackage, + windowsPackage, + purlPythonPackageWithLayerDetails, + purlHomebrewPackage, + }, + Findings: []*detector.Finding{ + { + Adv: &detector.Advisory{ + ID: &detector.AdvisoryID{ + Publisher: "CVE", + Reference: "CVE-1234", + }, + Type: detector.TypeVulnerability, + Title: "Title", + Description: "Description", + Recommendation: "Recommendation", + Sev: &detector.Severity{ + Severity: detector.SeverityMedium, + CVSSV2: &detector.CVSS{BaseScore: 1.0, TemporalScore: 2.0, EnvironmentalScore: 3.0}, + CVSSV3: &detector.CVSS{BaseScore: 4.0, TemporalScore: 5.0, EnvironmentalScore: 6.0}, + }, }, - Type: detector.TypeVulnerability, - Title: "Title", - Description: "Description", - Recommendation: "Recommendation", - Sev: &detector.Severity{ - Severity: detector.SeverityMedium, - CVSSV2: &detector.CVSS{BaseScore: 1.0, TemporalScore: 2.0, EnvironmentalScore: 3.0}, - CVSSV3: &detector.CVSS{BaseScore: 4.0, TemporalScore: 5.0, EnvironmentalScore: 6.0}, + Target: &detector.TargetDetails{ + Location: []string{"/file2"}, + Package: purlDPKGPackage, }, + Extra: "extra details", }, - Target: &detector.TargetDetails{ - Location: []string{"/file2"}, - Inventory: purlDPKGInventory, - }, - Extra: "extra details", }, }, }, @@ -825,40 +827,42 @@ func TestScanResultToProto(t *testing.T) { Status: successProto, }, }, - Inventories: []*spb.Inventory{ - purlDPKGInventoryProto, - purlDPKGAnnotationInventoryProto, - purlPythonInventoryProto, - pythonRequirementsInventoryProto, - purlJavascriptInventoryProto, - purlDotnetDepsJSONInventoryProto, - cdxInventoryProto, - windowsInventoryProto, - purlPythonInventoryWithLayerDetailsProto, - purlHomebrewInventoryProto, - }, - Findings: []*spb.Finding{ - { - Adv: &spb.Advisory{ - Id: &spb.AdvisoryId{ - Publisher: "CVE", - Reference: "CVE-1234", + Inventory: &spb.Inventory{ + Packages: []*spb.Package{ + purlDPKGPackageProto, + purlDPKGAnnotationPackageProto, + purlPythonPackageProto, + pythonRequirementsPackageProto, + purlJavascriptPackageProto, + purlDotnetDepsJSONPackageProto, + cdxPackageProto, + windowsPackageProto, + purlPythonPackageWithLayerDetailsProto, + purlHomebrewPackageProto, + }, + Findings: []*spb.Finding{ + { + Adv: &spb.Advisory{ + Id: &spb.AdvisoryId{ + Publisher: "CVE", + Reference: "CVE-1234", + }, + Type: spb.Advisory_VULNERABILITY, + Title: "Title", + Description: "Description", + Recommendation: "Recommendation", + Sev: &spb.Severity{ + Severity: spb.Severity_MEDIUM, + CvssV2: &spb.CVSS{BaseScore: 1.0, TemporalScore: 2.0, EnvironmentalScore: 3.0}, + CvssV3: &spb.CVSS{BaseScore: 4.0, TemporalScore: 5.0, EnvironmentalScore: 6.0}, + }, }, - Type: spb.Advisory_VULNERABILITY, - Title: "Title", - Description: "Description", - Recommendation: "Recommendation", - Sev: &spb.Severity{ - Severity: spb.Severity_MEDIUM, - CvssV2: &spb.CVSS{BaseScore: 1.0, TemporalScore: 2.0, EnvironmentalScore: 3.0}, - CvssV3: &spb.CVSS{BaseScore: 4.0, TemporalScore: 5.0, EnvironmentalScore: 6.0}, + Target: &spb.TargetDetails{ + Location: []string{"/file2"}, + Package: purlDPKGPackageProto, }, + Extra: "extra details", }, - Target: &spb.TargetDetails{ - Location: []string{"/file2"}, - Inventory: purlDPKGInventoryProto, - }, - Extra: "extra details", }, }, }, @@ -877,7 +881,9 @@ func TestScanResultToProto(t *testing.T) { Status: success, }, }, - Inventories: []*extractor.Inventory{purlRPMInventory}, + Inventory: &scalibr.Inventory{ + Packages: []*extractor.Package{purlRPMPackage}, + }, }, want: &spb.ScanResult{ Version: "1.0.0", @@ -891,8 +897,10 @@ func TestScanResultToProto(t *testing.T) { Status: successProto, }, }, - Inventories: []*spb.Inventory{purlRPMInventoryProto}, - Findings: []*spb.Finding{}, + Inventory: &spb.Inventory{ + Packages: []*spb.Package{purlRPMPackageProto}, + Findings: []*spb.Finding{}, + }, }, excludeForOS: []string{"windows", "darwin"}, }, @@ -910,7 +918,9 @@ func TestScanResultToProto(t *testing.T) { Status: success, }, }, - Inventories: []*extractor.Inventory{purlPACMANInventory}, + Inventory: &scalibr.Inventory{ + Packages: []*extractor.Package{purlPACMANPackage}, + }, }, want: &spb.ScanResult{ Version: "1.0.0", @@ -924,8 +934,10 @@ func TestScanResultToProto(t *testing.T) { Status: successProto, }, }, - Inventories: []*spb.Inventory{purlPACMANInventoryProto}, - Findings: []*spb.Finding{}, + Inventory: &spb.Inventory{ + Packages: []*spb.Package{purlPACMANPackageProto}, + Findings: []*spb.Finding{}, + }, }, excludeForOS: []string{"windows", "darwin"}, }, @@ -943,7 +955,9 @@ func TestScanResultToProto(t *testing.T) { Status: success, }, }, - Inventories: []*extractor.Inventory{purlPORTAGEInventory}, + Inventory: &scalibr.Inventory{ + Packages: []*extractor.Package{purlPORTAGEPackage}, + }, }, want: &spb.ScanResult{ Version: "1.0.0", @@ -957,8 +971,10 @@ func TestScanResultToProto(t *testing.T) { Status: successProto, }, }, - Inventories: []*spb.Inventory{purlPORTAGEInventoryProto}, - Findings: []*spb.Finding{}, + Inventory: &spb.Inventory{ + Packages: []*spb.Package{purlPORTAGEPackageProto}, + Findings: []*spb.Finding{}, + }, }, excludeForOS: []string{"windows", "darwin"}, }, @@ -976,7 +992,9 @@ func TestScanResultToProto(t *testing.T) { Status: success, }, }, - Inventories: []*extractor.Inventory{purlNixInventory}, + Inventory: &scalibr.Inventory{ + Packages: []*extractor.Package{purlNixPackage}, + }, }, want: &spb.ScanResult{ Version: "1.0.0", @@ -990,8 +1008,10 @@ func TestScanResultToProto(t *testing.T) { Status: successProto, }, }, - Inventories: []*spb.Inventory{purlNixInventoryProto}, - Findings: []*spb.Finding{}, + Inventory: &spb.Inventory{ + Packages: []*spb.Package{purlNixPackageProto}, + Findings: []*spb.Finding{}, + }, }, excludeForOS: []string{"windows", "darwin"}, }, @@ -1009,7 +1029,9 @@ func TestScanResultToProto(t *testing.T) { Status: success, }, }, - Inventories: []*extractor.Inventory{purlHomebrewInventory}, + Inventory: &scalibr.Inventory{ + Packages: []*extractor.Package{purlHomebrewPackage}, + }, }, want: &spb.ScanResult{ Version: "1.0.0", @@ -1023,8 +1045,10 @@ func TestScanResultToProto(t *testing.T) { Status: successProto, }, }, - Inventories: []*spb.Inventory{purlHomebrewInventoryProto}, - Findings: []*spb.Finding{}, + Inventory: &spb.Inventory{ + Packages: []*spb.Package{purlHomebrewPackageProto}, + Findings: []*spb.Finding{}, + }, }, excludeForOS: []string{"windows", "linux"}, }, @@ -1042,7 +1066,9 @@ func TestScanResultToProto(t *testing.T) { Status: success, }, }, - Inventories: []*extractor.Inventory{containerdInventory}, + Inventory: &scalibr.Inventory{ + Packages: []*extractor.Package{containerdPackage}, + }, }, want: &spb.ScanResult{ Version: "1.0.0", @@ -1056,8 +1082,10 @@ func TestScanResultToProto(t *testing.T) { Status: successProto, }, }, - Inventories: []*spb.Inventory{containerdInventoryProto}, - Findings: []*spb.Finding{}, + Inventory: &spb.Inventory{ + Packages: []*spb.Package{containerdPackageProto}, + Findings: []*spb.Finding{}, + }, }, // TODO(b/349138656): Remove windows from this exclusion when containerd is supported // on Windows. @@ -1077,7 +1105,9 @@ func TestScanResultToProto(t *testing.T) { Status: success, }, }, - Inventories: []*extractor.Inventory{containerdRuntimeInventory}, + Inventory: &scalibr.Inventory{ + Packages: []*extractor.Package{containerdRuntimePackage}, + }, }, want: &spb.ScanResult{ Version: "1.0.0", @@ -1091,15 +1121,17 @@ func TestScanResultToProto(t *testing.T) { Status: successProto, }, }, - Inventories: []*spb.Inventory{containerdRuntimeInventoryProto}, - Findings: []*spb.Finding{}, + Inventory: &spb.Inventory{ + Packages: []*spb.Package{containerdRuntimePackageProto}, + Findings: []*spb.Finding{}, + }, }, // TODO(b/349138656): Remove windows from this exclusion when containerd is supported // on Windows. excludeForOS: []string{"windows", "darwin"}, }, { - desc: "no inventory target, still works", + desc: "no package target, still works", res: &scalibr.ScanResult{ Version: "1.0.0", StartTime: startTime, @@ -1117,25 +1149,27 @@ func TestScanResultToProto(t *testing.T) { Status: success, }, }, - Inventories: []*extractor.Inventory{purlDPKGInventory, purlPythonInventory, purlJavascriptInventory, cdxInventory}, - Findings: []*detector.Finding{ - { - Adv: &detector.Advisory{ - ID: &detector.AdvisoryID{ - Publisher: "CVE", - Reference: "CVE-1234", - }, - Type: detector.TypeVulnerability, - Title: "Title", - Description: "Description", - Recommendation: "Recommendation", - Sev: &detector.Severity{ - Severity: detector.SeverityMedium, - CVSSV2: &detector.CVSS{BaseScore: 1.0, TemporalScore: 2.0, EnvironmentalScore: 3.0}, - CVSSV3: &detector.CVSS{BaseScore: 4.0, TemporalScore: 5.0, EnvironmentalScore: 6.0}, + Inventory: &scalibr.Inventory{ + Packages: []*extractor.Package{purlDPKGPackage, purlPythonPackage, purlJavascriptPackage, cdxPackage}, + Findings: []*detector.Finding{ + { + Adv: &detector.Advisory{ + ID: &detector.AdvisoryID{ + Publisher: "CVE", + Reference: "CVE-1234", + }, + Type: detector.TypeVulnerability, + Title: "Title", + Description: "Description", + Recommendation: "Recommendation", + Sev: &detector.Severity{ + Severity: detector.SeverityMedium, + CVSSV2: &detector.CVSS{BaseScore: 1.0, TemporalScore: 2.0, EnvironmentalScore: 3.0}, + CVSSV3: &detector.CVSS{BaseScore: 4.0, TemporalScore: 5.0, EnvironmentalScore: 6.0}, + }, }, + Extra: "extra details", }, - Extra: "extra details", }, }, }, @@ -1156,25 +1190,27 @@ func TestScanResultToProto(t *testing.T) { Status: successProto, }, }, - Inventories: []*spb.Inventory{purlDPKGInventoryProto, purlPythonInventoryProto, purlJavascriptInventoryProto, cdxInventoryProto}, - Findings: []*spb.Finding{ - { - Adv: &spb.Advisory{ - Id: &spb.AdvisoryId{ - Publisher: "CVE", - Reference: "CVE-1234", - }, - Type: spb.Advisory_VULNERABILITY, - Title: "Title", - Description: "Description", - Recommendation: "Recommendation", - Sev: &spb.Severity{ - Severity: spb.Severity_MEDIUM, - CvssV2: &spb.CVSS{BaseScore: 1.0, TemporalScore: 2.0, EnvironmentalScore: 3.0}, - CvssV3: &spb.CVSS{BaseScore: 4.0, TemporalScore: 5.0, EnvironmentalScore: 6.0}, + Inventory: &spb.Inventory{ + Packages: []*spb.Package{purlDPKGPackageProto, purlPythonPackageProto, purlJavascriptPackageProto, cdxPackageProto}, + Findings: []*spb.Finding{ + { + Adv: &spb.Advisory{ + Id: &spb.AdvisoryId{ + Publisher: "CVE", + Reference: "CVE-1234", + }, + Type: spb.Advisory_VULNERABILITY, + Title: "Title", + Description: "Description", + Recommendation: "Recommendation", + Sev: &spb.Severity{ + Severity: spb.Severity_MEDIUM, + CvssV2: &spb.CVSS{BaseScore: 1.0, TemporalScore: 2.0, EnvironmentalScore: 3.0}, + CvssV3: &spb.CVSS{BaseScore: 4.0, TemporalScore: 5.0, EnvironmentalScore: 6.0}, + }, }, + Extra: "extra details", }, - Extra: "extra details", }, }, }, @@ -1198,21 +1234,23 @@ func TestScanResultToProto(t *testing.T) { Status: success, }, }, - Inventories: []*extractor.Inventory{purlDPKGInventory, purlPythonInventory, purlJavascriptInventory, cdxInventory}, - Findings: []*detector.Finding{ - { - Adv: &detector.Advisory{ - Type: detector.TypeVulnerability, - Title: "Title", - Description: "Description", - Recommendation: "Recommendation", - Sev: &detector.Severity{ - Severity: detector.SeverityMedium, - CVSSV2: &detector.CVSS{BaseScore: 1.0, TemporalScore: 2.0, EnvironmentalScore: 3.0}, - CVSSV3: &detector.CVSS{BaseScore: 4.0, TemporalScore: 5.0, EnvironmentalScore: 6.0}, + Inventory: &scalibr.Inventory{ + Packages: []*extractor.Package{purlDPKGPackage, purlPythonPackage, purlJavascriptPackage, cdxPackage}, + Findings: []*detector.Finding{ + { + Adv: &detector.Advisory{ + Type: detector.TypeVulnerability, + Title: "Title", + Description: "Description", + Recommendation: "Recommendation", + Sev: &detector.Severity{ + Severity: detector.SeverityMedium, + CVSSV2: &detector.CVSS{BaseScore: 1.0, TemporalScore: 2.0, EnvironmentalScore: 3.0}, + CVSSV3: &detector.CVSS{BaseScore: 4.0, TemporalScore: 5.0, EnvironmentalScore: 6.0}, + }, }, + Extra: "extra details", }, - Extra: "extra details", }, }, }, @@ -1237,10 +1275,12 @@ func TestScanResultToProto(t *testing.T) { Status: success, }, }, - Inventories: []*extractor.Inventory{purlDPKGInventory, purlPythonInventory, purlJavascriptInventory, cdxInventory}, - Findings: []*detector.Finding{ - { - Extra: "extra details", + Inventory: &scalibr.Inventory{ + Packages: []*extractor.Package{purlDPKGPackage, purlPythonPackage, purlJavascriptPackage, cdxPackage}, + Findings: []*detector.Finding{ + { + Extra: "extra details", + }, }, }, }, @@ -1253,6 +1293,7 @@ func TestScanResultToProto(t *testing.T) { StartTime: startTime, EndTime: endTime, Status: failure, + Inventory: &scalibr.Inventory{}, PluginStatus: []*plugin.Status{ { Name: "ext", @@ -1271,6 +1312,7 @@ func TestScanResultToProto(t *testing.T) { StartTime: timestamppb.New(startTime), EndTime: timestamppb.New(endTime), Status: failureProto, + Inventory: &spb.Inventory{}, PluginStatus: []*spb.PluginStatus{ { Name: "ext", @@ -1297,6 +1339,15 @@ func TestScanResultToProto(t *testing.T) { if err != tc.wantErr { t.Fatalf("proto.ScanResultToProto(%v) err: got %v, want %v", tc.res, err, tc.wantErr) } + + // Ignore deprecated fields in the comparison. + // TODO(b/400910349): Stop setting the deprecated fields + // once integrators no longer read them. + if got != nil { + got.InventoriesDeprecated = nil + got.FindingsDeprecated = nil + } + if diff := cmp.Diff(tc.want, got, protocmp.Transform()); diff != "" { t.Errorf("check.Exec() returned unexpected diff (-want +got):\n%s", diff) } diff --git a/binary/proto/scan_result.proto b/binary/proto/scan_result.proto index 9bb0bc55..45fc9cee 100644 --- a/binary/proto/scan_result.proto +++ b/binary/proto/scan_result.proto @@ -27,17 +27,25 @@ option java_multiple_files = true; // modified make sure to regenerate the go_proto file by running // `make protos` -// The software inventory and security findings that a scan run found. +// The results of a scan incl. scan status and artifacts found. message ScanResult { string version = 1; google.protobuf.Timestamp start_time = 2; google.protobuf.Timestamp end_time = 3; // Status of the overall scan. ScanStatus status = 4; - // Status and versions of the inventory+vuln plugins that ran. + // Status and versions of the plugins that ran. repeated PluginStatus plugin_status = 5; - repeated Inventory inventories = 6; - repeated Finding findings = 7; + // TODO(b/400910349): Remove once integrators stop using these fields. + repeated Package inventories_deprecated = 6 [deprecated = true]; + repeated Finding findings_deprecated = 7 [deprecated = true]; + Inventory inventory = 8; +} + +// The artifacts (e.g. software inventory, security findings) that a scan found. +message Inventory { + repeated Package packages = 1; + repeated Finding findings = 2; } message ScanStatus { @@ -59,7 +67,7 @@ message PluginStatus { // A software package or library found by an extractor. // PURL or CPE needs to be set, maybe both. -message Inventory { +message Package { reserved 3, 4; // Human-readable name of the software, to be used for things like logging. // For vuln matching, use the name from metadata. @@ -224,8 +232,8 @@ message CVSS { message TargetDetails { // The software affected by the finding. - Inventory inventory = 1; - // Location of vulnerable files not related to the inventory, + Package package = 1; + // Location of vulnerable files not related to the package, // e.g. config files with misconfigurations. repeated string location = 3; } diff --git a/binary/proto/scan_result_go_proto/scan_result.pb.go b/binary/proto/scan_result_go_proto/scan_result.pb.go index ca477dca..43cf3dec 100644 --- a/binary/proto/scan_result_go_proto/scan_result.pb.go +++ b/binary/proto/scan_result_go_proto/scan_result.pb.go @@ -16,7 +16,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.35.1 -// protoc v3.21.12 +// protoc v3.21.1 // source: proto/scan_result.proto package scan_result_go_proto @@ -85,27 +85,27 @@ func (x ScanStatus_ScanStatusEnum) Number() protoreflect.EnumNumber { // Deprecated: Use ScanStatus_ScanStatusEnum.Descriptor instead. func (ScanStatus_ScanStatusEnum) EnumDescriptor() ([]byte, []int) { - return file_proto_scan_result_proto_rawDescGZIP(), []int{1, 0} + return file_proto_scan_result_proto_rawDescGZIP(), []int{2, 0} } -type Inventory_AnnotationEnum int32 +type Package_AnnotationEnum int32 const ( - Inventory_UNSPECIFIED Inventory_AnnotationEnum = 0 - Inventory_TRANSITIONAL Inventory_AnnotationEnum = 1 - Inventory_INSIDE_OS_PACKAGE Inventory_AnnotationEnum = 2 - Inventory_INSIDE_CACHE_DIR Inventory_AnnotationEnum = 3 + Package_UNSPECIFIED Package_AnnotationEnum = 0 + Package_TRANSITIONAL Package_AnnotationEnum = 1 + Package_INSIDE_OS_PACKAGE Package_AnnotationEnum = 2 + Package_INSIDE_CACHE_DIR Package_AnnotationEnum = 3 ) -// Enum value maps for Inventory_AnnotationEnum. +// Enum value maps for Package_AnnotationEnum. var ( - Inventory_AnnotationEnum_name = map[int32]string{ + Package_AnnotationEnum_name = map[int32]string{ 0: "UNSPECIFIED", 1: "TRANSITIONAL", 2: "INSIDE_OS_PACKAGE", 3: "INSIDE_CACHE_DIR", } - Inventory_AnnotationEnum_value = map[string]int32{ + Package_AnnotationEnum_value = map[string]int32{ "UNSPECIFIED": 0, "TRANSITIONAL": 1, "INSIDE_OS_PACKAGE": 2, @@ -113,31 +113,31 @@ var ( } ) -func (x Inventory_AnnotationEnum) Enum() *Inventory_AnnotationEnum { - p := new(Inventory_AnnotationEnum) +func (x Package_AnnotationEnum) Enum() *Package_AnnotationEnum { + p := new(Package_AnnotationEnum) *p = x return p } -func (x Inventory_AnnotationEnum) String() string { +func (x Package_AnnotationEnum) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } -func (Inventory_AnnotationEnum) Descriptor() protoreflect.EnumDescriptor { +func (Package_AnnotationEnum) Descriptor() protoreflect.EnumDescriptor { return file_proto_scan_result_proto_enumTypes[1].Descriptor() } -func (Inventory_AnnotationEnum) Type() protoreflect.EnumType { +func (Package_AnnotationEnum) Type() protoreflect.EnumType { return &file_proto_scan_result_proto_enumTypes[1] } -func (x Inventory_AnnotationEnum) Number() protoreflect.EnumNumber { +func (x Package_AnnotationEnum) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } -// Deprecated: Use Inventory_AnnotationEnum.Descriptor instead. -func (Inventory_AnnotationEnum) EnumDescriptor() ([]byte, []int) { - return file_proto_scan_result_proto_rawDescGZIP(), []int{3, 0} +// Deprecated: Use Package_AnnotationEnum.Descriptor instead. +func (Package_AnnotationEnum) EnumDescriptor() ([]byte, []int) { + return file_proto_scan_result_proto_rawDescGZIP(), []int{4, 0} } type Advisory_TypeEnum int32 @@ -186,7 +186,7 @@ func (x Advisory_TypeEnum) Number() protoreflect.EnumNumber { // Deprecated: Use Advisory_TypeEnum.Descriptor instead. func (Advisory_TypeEnum) EnumDescriptor() ([]byte, []int) { - return file_proto_scan_result_proto_rawDescGZIP(), []int{9, 0} + return file_proto_scan_result_proto_rawDescGZIP(), []int{10, 0} } type Severity_SeverityEnum int32 @@ -244,10 +244,10 @@ func (x Severity_SeverityEnum) Number() protoreflect.EnumNumber { // Deprecated: Use Severity_SeverityEnum.Descriptor instead. func (Severity_SeverityEnum) EnumDescriptor() ([]byte, []int) { - return file_proto_scan_result_proto_rawDescGZIP(), []int{11, 0} + return file_proto_scan_result_proto_rawDescGZIP(), []int{12, 0} } -// The software inventory and security findings that a scan run found. +// The results of a scan incl. scan status and artifacts found. type ScanResult struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -258,10 +258,15 @@ type ScanResult struct { EndTime *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=end_time,json=endTime,proto3" json:"end_time,omitempty"` // Status of the overall scan. Status *ScanStatus `protobuf:"bytes,4,opt,name=status,proto3" json:"status,omitempty"` - // Status and versions of the inventory+vuln plugins that ran. + // Status and versions of the plugins that ran. PluginStatus []*PluginStatus `protobuf:"bytes,5,rep,name=plugin_status,json=pluginStatus,proto3" json:"plugin_status,omitempty"` - Inventories []*Inventory `protobuf:"bytes,6,rep,name=inventories,proto3" json:"inventories,omitempty"` - Findings []*Finding `protobuf:"bytes,7,rep,name=findings,proto3" json:"findings,omitempty"` + // TODO(b/400910349): Remove once integrators stop using these fields. + // + // Deprecated: Marked as deprecated in proto/scan_result.proto. + InventoriesDeprecated []*Package `protobuf:"bytes,6,rep,name=inventories_deprecated,json=inventoriesDeprecated,proto3" json:"inventories_deprecated,omitempty"` + // Deprecated: Marked as deprecated in proto/scan_result.proto. + FindingsDeprecated []*Finding `protobuf:"bytes,7,rep,name=findings_deprecated,json=findingsDeprecated,proto3" json:"findings_deprecated,omitempty"` + Inventory *Inventory `protobuf:"bytes,8,opt,name=inventory,proto3" json:"inventory,omitempty"` } func (x *ScanResult) Reset() { @@ -329,14 +334,77 @@ func (x *ScanResult) GetPluginStatus() []*PluginStatus { return nil } -func (x *ScanResult) GetInventories() []*Inventory { +// Deprecated: Marked as deprecated in proto/scan_result.proto. +func (x *ScanResult) GetInventoriesDeprecated() []*Package { + if x != nil { + return x.InventoriesDeprecated + } + return nil +} + +// Deprecated: Marked as deprecated in proto/scan_result.proto. +func (x *ScanResult) GetFindingsDeprecated() []*Finding { + if x != nil { + return x.FindingsDeprecated + } + return nil +} + +func (x *ScanResult) GetInventory() *Inventory { + if x != nil { + return x.Inventory + } + return nil +} + +// The artifacts (e.g. software inventory, security findings) that a scan found. +type Inventory struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Packages []*Package `protobuf:"bytes,1,rep,name=packages,proto3" json:"packages,omitempty"` + Findings []*Finding `protobuf:"bytes,2,rep,name=findings,proto3" json:"findings,omitempty"` +} + +func (x *Inventory) Reset() { + *x = Inventory{} + mi := &file_proto_scan_result_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Inventory) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Inventory) ProtoMessage() {} + +func (x *Inventory) ProtoReflect() protoreflect.Message { + mi := &file_proto_scan_result_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Inventory.ProtoReflect.Descriptor instead. +func (*Inventory) Descriptor() ([]byte, []int) { + return file_proto_scan_result_proto_rawDescGZIP(), []int{1} +} + +func (x *Inventory) GetPackages() []*Package { if x != nil { - return x.Inventories + return x.Packages } return nil } -func (x *ScanResult) GetFindings() []*Finding { +func (x *Inventory) GetFindings() []*Finding { if x != nil { return x.Findings } @@ -354,7 +422,7 @@ type ScanStatus struct { func (x *ScanStatus) Reset() { *x = ScanStatus{} - mi := &file_proto_scan_result_proto_msgTypes[1] + mi := &file_proto_scan_result_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -366,7 +434,7 @@ func (x *ScanStatus) String() string { func (*ScanStatus) ProtoMessage() {} func (x *ScanStatus) ProtoReflect() protoreflect.Message { - mi := &file_proto_scan_result_proto_msgTypes[1] + mi := &file_proto_scan_result_proto_msgTypes[2] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -379,7 +447,7 @@ func (x *ScanStatus) ProtoReflect() protoreflect.Message { // Deprecated: Use ScanStatus.ProtoReflect.Descriptor instead. func (*ScanStatus) Descriptor() ([]byte, []int) { - return file_proto_scan_result_proto_rawDescGZIP(), []int{1} + return file_proto_scan_result_proto_rawDescGZIP(), []int{2} } func (x *ScanStatus) GetStatus() ScanStatus_ScanStatusEnum { @@ -408,7 +476,7 @@ type PluginStatus struct { func (x *PluginStatus) Reset() { *x = PluginStatus{} - mi := &file_proto_scan_result_proto_msgTypes[2] + mi := &file_proto_scan_result_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -420,7 +488,7 @@ func (x *PluginStatus) String() string { func (*PluginStatus) ProtoMessage() {} func (x *PluginStatus) ProtoReflect() protoreflect.Message { - mi := &file_proto_scan_result_proto_msgTypes[2] + mi := &file_proto_scan_result_proto_msgTypes[3] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -433,7 +501,7 @@ func (x *PluginStatus) ProtoReflect() protoreflect.Message { // Deprecated: Use PluginStatus.ProtoReflect.Descriptor instead. func (*PluginStatus) Descriptor() ([]byte, []int) { - return file_proto_scan_result_proto_rawDescGZIP(), []int{2} + return file_proto_scan_result_proto_rawDescGZIP(), []int{3} } func (x *PluginStatus) GetName() string { @@ -459,7 +527,7 @@ func (x *PluginStatus) GetStatus() *ScanStatus { // A software package or library found by an extractor. // PURL or CPE needs to be set, maybe both. -type Inventory struct { +type Package struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields @@ -485,54 +553,54 @@ type Inventory struct { // // Types that are assignable to Metadata: // - // *Inventory_PythonMetadata - // *Inventory_JavascriptMetadata - // *Inventory_ApkMetadata - // *Inventory_DpkgMetadata - // *Inventory_RpmMetadata - // *Inventory_CosMetadata - // *Inventory_DepsjsonMetadata - // *Inventory_SpdxMetadata - // *Inventory_JavaArchiveMetadata - // *Inventory_JavaLockfileMetadata - // *Inventory_PacmanMetadata - // *Inventory_NixMetadata - // *Inventory_KernelModuleMetadata - // *Inventory_VmlinuzMetadata - // *Inventory_PortageMetadata - // *Inventory_OsvMetadata - // *Inventory_PythonRequirementsMetadata - // *Inventory_PythonSetupMetadata - // *Inventory_ContainerdContainerMetadata - // *Inventory_SnapMetadata - // *Inventory_FlatpakMetadata - // *Inventory_MacAppsMetadata - // *Inventory_ContainerdRuntimeContainerMetadata - // *Inventory_CdxMetadata - // *Inventory_WindowsOsVersionMetadata - // *Inventory_HomebrewMetadata - Metadata isInventory_Metadata `protobuf_oneof:"metadata"` - Annotations []Inventory_AnnotationEnum `protobuf:"varint,28,rep,packed,name=annotations,proto3,enum=scalibr.Inventory_AnnotationEnum" json:"annotations,omitempty"` + // *Package_PythonMetadata + // *Package_JavascriptMetadata + // *Package_ApkMetadata + // *Package_DpkgMetadata + // *Package_RpmMetadata + // *Package_CosMetadata + // *Package_DepsjsonMetadata + // *Package_SpdxMetadata + // *Package_JavaArchiveMetadata + // *Package_JavaLockfileMetadata + // *Package_PacmanMetadata + // *Package_NixMetadata + // *Package_KernelModuleMetadata + // *Package_VmlinuzMetadata + // *Package_PortageMetadata + // *Package_OsvMetadata + // *Package_PythonRequirementsMetadata + // *Package_PythonSetupMetadata + // *Package_ContainerdContainerMetadata + // *Package_SnapMetadata + // *Package_FlatpakMetadata + // *Package_MacAppsMetadata + // *Package_ContainerdRuntimeContainerMetadata + // *Package_CdxMetadata + // *Package_WindowsOsVersionMetadata + // *Package_HomebrewMetadata + Metadata isPackage_Metadata `protobuf_oneof:"metadata"` + Annotations []Package_AnnotationEnum `protobuf:"varint,28,rep,packed,name=annotations,proto3,enum=scalibr.Package_AnnotationEnum" json:"annotations,omitempty"` // Details about the layer a package was found in. This should be set only for // container image scanning. LayerDetails *LayerDetails `protobuf:"bytes,35,opt,name=layer_details,json=layerDetails,proto3" json:"layer_details,omitempty"` } -func (x *Inventory) Reset() { - *x = Inventory{} - mi := &file_proto_scan_result_proto_msgTypes[3] +func (x *Package) Reset() { + *x = Package{} + mi := &file_proto_scan_result_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *Inventory) String() string { +func (x *Package) String() string { return protoimpl.X.MessageStringOf(x) } -func (*Inventory) ProtoMessage() {} +func (*Package) ProtoMessage() {} -func (x *Inventory) ProtoReflect() protoreflect.Message { - mi := &file_proto_scan_result_proto_msgTypes[3] +func (x *Package) ProtoReflect() protoreflect.Message { + mi := &file_proto_scan_result_proto_msgTypes[4] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -543,422 +611,422 @@ func (x *Inventory) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use Inventory.ProtoReflect.Descriptor instead. -func (*Inventory) Descriptor() ([]byte, []int) { - return file_proto_scan_result_proto_rawDescGZIP(), []int{3} +// Deprecated: Use Package.ProtoReflect.Descriptor instead. +func (*Package) Descriptor() ([]byte, []int) { + return file_proto_scan_result_proto_rawDescGZIP(), []int{4} } -func (x *Inventory) GetName() string { +func (x *Package) GetName() string { if x != nil { return x.Name } return "" } -func (x *Inventory) GetVersion() string { +func (x *Package) GetVersion() string { if x != nil { return x.Version } return "" } -func (x *Inventory) GetSourceCode() *SourceCodeIdentifier { +func (x *Package) GetSourceCode() *SourceCodeIdentifier { if x != nil { return x.SourceCode } return nil } -func (x *Inventory) GetPurl() *Purl { +func (x *Package) GetPurl() *Purl { if x != nil { return x.Purl } return nil } -func (x *Inventory) GetEcosystem() string { +func (x *Package) GetEcosystem() string { if x != nil { return x.Ecosystem } return "" } -func (x *Inventory) GetLocations() []string { +func (x *Package) GetLocations() []string { if x != nil { return x.Locations } return nil } -func (x *Inventory) GetExtractor() string { +func (x *Package) GetExtractor() string { if x != nil { return x.Extractor } return "" } -func (m *Inventory) GetMetadata() isInventory_Metadata { +func (m *Package) GetMetadata() isPackage_Metadata { if m != nil { return m.Metadata } return nil } -func (x *Inventory) GetPythonMetadata() *PythonPackageMetadata { - if x, ok := x.GetMetadata().(*Inventory_PythonMetadata); ok { +func (x *Package) GetPythonMetadata() *PythonPackageMetadata { + if x, ok := x.GetMetadata().(*Package_PythonMetadata); ok { return x.PythonMetadata } return nil } -func (x *Inventory) GetJavascriptMetadata() *JavascriptPackageJSONMetadata { - if x, ok := x.GetMetadata().(*Inventory_JavascriptMetadata); ok { +func (x *Package) GetJavascriptMetadata() *JavascriptPackageJSONMetadata { + if x, ok := x.GetMetadata().(*Package_JavascriptMetadata); ok { return x.JavascriptMetadata } return nil } -func (x *Inventory) GetApkMetadata() *APKPackageMetadata { - if x, ok := x.GetMetadata().(*Inventory_ApkMetadata); ok { +func (x *Package) GetApkMetadata() *APKPackageMetadata { + if x, ok := x.GetMetadata().(*Package_ApkMetadata); ok { return x.ApkMetadata } return nil } -func (x *Inventory) GetDpkgMetadata() *DPKGPackageMetadata { - if x, ok := x.GetMetadata().(*Inventory_DpkgMetadata); ok { +func (x *Package) GetDpkgMetadata() *DPKGPackageMetadata { + if x, ok := x.GetMetadata().(*Package_DpkgMetadata); ok { return x.DpkgMetadata } return nil } -func (x *Inventory) GetRpmMetadata() *RPMPackageMetadata { - if x, ok := x.GetMetadata().(*Inventory_RpmMetadata); ok { +func (x *Package) GetRpmMetadata() *RPMPackageMetadata { + if x, ok := x.GetMetadata().(*Package_RpmMetadata); ok { return x.RpmMetadata } return nil } -func (x *Inventory) GetCosMetadata() *COSPackageMetadata { - if x, ok := x.GetMetadata().(*Inventory_CosMetadata); ok { +func (x *Package) GetCosMetadata() *COSPackageMetadata { + if x, ok := x.GetMetadata().(*Package_CosMetadata); ok { return x.CosMetadata } return nil } -func (x *Inventory) GetDepsjsonMetadata() *DEPSJSONMetadata { - if x, ok := x.GetMetadata().(*Inventory_DepsjsonMetadata); ok { +func (x *Package) GetDepsjsonMetadata() *DEPSJSONMetadata { + if x, ok := x.GetMetadata().(*Package_DepsjsonMetadata); ok { return x.DepsjsonMetadata } return nil } -func (x *Inventory) GetSpdxMetadata() *SPDXPackageMetadata { - if x, ok := x.GetMetadata().(*Inventory_SpdxMetadata); ok { +func (x *Package) GetSpdxMetadata() *SPDXPackageMetadata { + if x, ok := x.GetMetadata().(*Package_SpdxMetadata); ok { return x.SpdxMetadata } return nil } -func (x *Inventory) GetJavaArchiveMetadata() *JavaArchiveMetadata { - if x, ok := x.GetMetadata().(*Inventory_JavaArchiveMetadata); ok { +func (x *Package) GetJavaArchiveMetadata() *JavaArchiveMetadata { + if x, ok := x.GetMetadata().(*Package_JavaArchiveMetadata); ok { return x.JavaArchiveMetadata } return nil } -func (x *Inventory) GetJavaLockfileMetadata() *JavaLockfileMetadata { - if x, ok := x.GetMetadata().(*Inventory_JavaLockfileMetadata); ok { +func (x *Package) GetJavaLockfileMetadata() *JavaLockfileMetadata { + if x, ok := x.GetMetadata().(*Package_JavaLockfileMetadata); ok { return x.JavaLockfileMetadata } return nil } -func (x *Inventory) GetPacmanMetadata() *PACMANPackageMetadata { - if x, ok := x.GetMetadata().(*Inventory_PacmanMetadata); ok { +func (x *Package) GetPacmanMetadata() *PACMANPackageMetadata { + if x, ok := x.GetMetadata().(*Package_PacmanMetadata); ok { return x.PacmanMetadata } return nil } -func (x *Inventory) GetNixMetadata() *NixPackageMetadata { - if x, ok := x.GetMetadata().(*Inventory_NixMetadata); ok { +func (x *Package) GetNixMetadata() *NixPackageMetadata { + if x, ok := x.GetMetadata().(*Package_NixMetadata); ok { return x.NixMetadata } return nil } -func (x *Inventory) GetKernelModuleMetadata() *KernelModuleMetadata { - if x, ok := x.GetMetadata().(*Inventory_KernelModuleMetadata); ok { +func (x *Package) GetKernelModuleMetadata() *KernelModuleMetadata { + if x, ok := x.GetMetadata().(*Package_KernelModuleMetadata); ok { return x.KernelModuleMetadata } return nil } -func (x *Inventory) GetVmlinuzMetadata() *VmlinuzMetadata { - if x, ok := x.GetMetadata().(*Inventory_VmlinuzMetadata); ok { +func (x *Package) GetVmlinuzMetadata() *VmlinuzMetadata { + if x, ok := x.GetMetadata().(*Package_VmlinuzMetadata); ok { return x.VmlinuzMetadata } return nil } -func (x *Inventory) GetPortageMetadata() *PortagePackageMetadata { - if x, ok := x.GetMetadata().(*Inventory_PortageMetadata); ok { +func (x *Package) GetPortageMetadata() *PortagePackageMetadata { + if x, ok := x.GetMetadata().(*Package_PortageMetadata); ok { return x.PortageMetadata } return nil } -func (x *Inventory) GetOsvMetadata() *OSVPackageMetadata { - if x, ok := x.GetMetadata().(*Inventory_OsvMetadata); ok { +func (x *Package) GetOsvMetadata() *OSVPackageMetadata { + if x, ok := x.GetMetadata().(*Package_OsvMetadata); ok { return x.OsvMetadata } return nil } -func (x *Inventory) GetPythonRequirementsMetadata() *PythonRequirementsMetadata { - if x, ok := x.GetMetadata().(*Inventory_PythonRequirementsMetadata); ok { +func (x *Package) GetPythonRequirementsMetadata() *PythonRequirementsMetadata { + if x, ok := x.GetMetadata().(*Package_PythonRequirementsMetadata); ok { return x.PythonRequirementsMetadata } return nil } -func (x *Inventory) GetPythonSetupMetadata() *PythonSetupMetadata { - if x, ok := x.GetMetadata().(*Inventory_PythonSetupMetadata); ok { +func (x *Package) GetPythonSetupMetadata() *PythonSetupMetadata { + if x, ok := x.GetMetadata().(*Package_PythonSetupMetadata); ok { return x.PythonSetupMetadata } return nil } -func (x *Inventory) GetContainerdContainerMetadata() *ContainerdContainerMetadata { - if x, ok := x.GetMetadata().(*Inventory_ContainerdContainerMetadata); ok { +func (x *Package) GetContainerdContainerMetadata() *ContainerdContainerMetadata { + if x, ok := x.GetMetadata().(*Package_ContainerdContainerMetadata); ok { return x.ContainerdContainerMetadata } return nil } -func (x *Inventory) GetSnapMetadata() *SNAPPackageMetadata { - if x, ok := x.GetMetadata().(*Inventory_SnapMetadata); ok { +func (x *Package) GetSnapMetadata() *SNAPPackageMetadata { + if x, ok := x.GetMetadata().(*Package_SnapMetadata); ok { return x.SnapMetadata } return nil } -func (x *Inventory) GetFlatpakMetadata() *FlatpakPackageMetadata { - if x, ok := x.GetMetadata().(*Inventory_FlatpakMetadata); ok { +func (x *Package) GetFlatpakMetadata() *FlatpakPackageMetadata { + if x, ok := x.GetMetadata().(*Package_FlatpakMetadata); ok { return x.FlatpakMetadata } return nil } -func (x *Inventory) GetMacAppsMetadata() *MacAppsMetadata { - if x, ok := x.GetMetadata().(*Inventory_MacAppsMetadata); ok { +func (x *Package) GetMacAppsMetadata() *MacAppsMetadata { + if x, ok := x.GetMetadata().(*Package_MacAppsMetadata); ok { return x.MacAppsMetadata } return nil } -func (x *Inventory) GetContainerdRuntimeContainerMetadata() *ContainerdRuntimeContainerMetadata { - if x, ok := x.GetMetadata().(*Inventory_ContainerdRuntimeContainerMetadata); ok { +func (x *Package) GetContainerdRuntimeContainerMetadata() *ContainerdRuntimeContainerMetadata { + if x, ok := x.GetMetadata().(*Package_ContainerdRuntimeContainerMetadata); ok { return x.ContainerdRuntimeContainerMetadata } return nil } -func (x *Inventory) GetCdxMetadata() *CDXPackageMetadata { - if x, ok := x.GetMetadata().(*Inventory_CdxMetadata); ok { +func (x *Package) GetCdxMetadata() *CDXPackageMetadata { + if x, ok := x.GetMetadata().(*Package_CdxMetadata); ok { return x.CdxMetadata } return nil } -func (x *Inventory) GetWindowsOsVersionMetadata() *WindowsOSVersion { - if x, ok := x.GetMetadata().(*Inventory_WindowsOsVersionMetadata); ok { +func (x *Package) GetWindowsOsVersionMetadata() *WindowsOSVersion { + if x, ok := x.GetMetadata().(*Package_WindowsOsVersionMetadata); ok { return x.WindowsOsVersionMetadata } return nil } -func (x *Inventory) GetHomebrewMetadata() *HomebrewPackageMetadata { - if x, ok := x.GetMetadata().(*Inventory_HomebrewMetadata); ok { +func (x *Package) GetHomebrewMetadata() *HomebrewPackageMetadata { + if x, ok := x.GetMetadata().(*Package_HomebrewMetadata); ok { return x.HomebrewMetadata } return nil } -func (x *Inventory) GetAnnotations() []Inventory_AnnotationEnum { +func (x *Package) GetAnnotations() []Package_AnnotationEnum { if x != nil { return x.Annotations } return nil } -func (x *Inventory) GetLayerDetails() *LayerDetails { +func (x *Package) GetLayerDetails() *LayerDetails { if x != nil { return x.LayerDetails } return nil } -type isInventory_Metadata interface { - isInventory_Metadata() +type isPackage_Metadata interface { + isPackage_Metadata() } -type Inventory_PythonMetadata struct { +type Package_PythonMetadata struct { PythonMetadata *PythonPackageMetadata `protobuf:"bytes,5,opt,name=python_metadata,json=pythonMetadata,proto3,oneof"` } -type Inventory_JavascriptMetadata struct { +type Package_JavascriptMetadata struct { JavascriptMetadata *JavascriptPackageJSONMetadata `protobuf:"bytes,6,opt,name=javascript_metadata,json=javascriptMetadata,proto3,oneof"` } -type Inventory_ApkMetadata struct { +type Package_ApkMetadata struct { ApkMetadata *APKPackageMetadata `protobuf:"bytes,7,opt,name=apk_metadata,json=apkMetadata,proto3,oneof"` } -type Inventory_DpkgMetadata struct { +type Package_DpkgMetadata struct { DpkgMetadata *DPKGPackageMetadata `protobuf:"bytes,8,opt,name=dpkg_metadata,json=dpkgMetadata,proto3,oneof"` } -type Inventory_RpmMetadata struct { +type Package_RpmMetadata struct { RpmMetadata *RPMPackageMetadata `protobuf:"bytes,9,opt,name=rpm_metadata,json=rpmMetadata,proto3,oneof"` } -type Inventory_CosMetadata struct { +type Package_CosMetadata struct { CosMetadata *COSPackageMetadata `protobuf:"bytes,13,opt,name=cos_metadata,json=cosMetadata,proto3,oneof"` } -type Inventory_DepsjsonMetadata struct { +type Package_DepsjsonMetadata struct { DepsjsonMetadata *DEPSJSONMetadata `protobuf:"bytes,40,opt,name=depsjson_metadata,json=depsjsonMetadata,proto3,oneof"` } -type Inventory_SpdxMetadata struct { +type Package_SpdxMetadata struct { SpdxMetadata *SPDXPackageMetadata `protobuf:"bytes,14,opt,name=spdx_metadata,json=spdxMetadata,proto3,oneof"` } -type Inventory_JavaArchiveMetadata struct { +type Package_JavaArchiveMetadata struct { JavaArchiveMetadata *JavaArchiveMetadata `protobuf:"bytes,15,opt,name=java_archive_metadata,json=javaArchiveMetadata,proto3,oneof"` } -type Inventory_JavaLockfileMetadata struct { +type Package_JavaLockfileMetadata struct { JavaLockfileMetadata *JavaLockfileMetadata `protobuf:"bytes,31,opt,name=java_lockfile_metadata,json=javaLockfileMetadata,proto3,oneof"` } -type Inventory_PacmanMetadata struct { +type Package_PacmanMetadata struct { PacmanMetadata *PACMANPackageMetadata `protobuf:"bytes,36,opt,name=pacman_metadata,json=pacmanMetadata,proto3,oneof"` } -type Inventory_NixMetadata struct { +type Package_NixMetadata struct { NixMetadata *NixPackageMetadata `protobuf:"bytes,37,opt,name=nix_metadata,json=nixMetadata,proto3,oneof"` } -type Inventory_KernelModuleMetadata struct { +type Package_KernelModuleMetadata struct { KernelModuleMetadata *KernelModuleMetadata `protobuf:"bytes,38,opt,name=kernel_module_metadata,json=kernelModuleMetadata,proto3,oneof"` } -type Inventory_VmlinuzMetadata struct { +type Package_VmlinuzMetadata struct { VmlinuzMetadata *VmlinuzMetadata `protobuf:"bytes,39,opt,name=vmlinuz_metadata,json=vmlinuzMetadata,proto3,oneof"` } -type Inventory_PortageMetadata struct { +type Package_PortageMetadata struct { PortageMetadata *PortagePackageMetadata `protobuf:"bytes,41,opt,name=portage_metadata,json=portageMetadata,proto3,oneof"` } -type Inventory_OsvMetadata struct { +type Package_OsvMetadata struct { OsvMetadata *OSVPackageMetadata `protobuf:"bytes,16,opt,name=osv_metadata,json=osvMetadata,proto3,oneof"` } -type Inventory_PythonRequirementsMetadata struct { +type Package_PythonRequirementsMetadata struct { PythonRequirementsMetadata *PythonRequirementsMetadata `protobuf:"bytes,21,opt,name=python_requirements_metadata,json=pythonRequirementsMetadata,proto3,oneof"` } -type Inventory_PythonSetupMetadata struct { +type Package_PythonSetupMetadata struct { PythonSetupMetadata *PythonSetupMetadata `protobuf:"bytes,44,opt,name=python_setup_metadata,json=pythonSetupMetadata,proto3,oneof"` } -type Inventory_ContainerdContainerMetadata struct { +type Package_ContainerdContainerMetadata struct { ContainerdContainerMetadata *ContainerdContainerMetadata `protobuf:"bytes,22,opt,name=containerd_container_metadata,json=containerdContainerMetadata,proto3,oneof"` } -type Inventory_SnapMetadata struct { +type Package_SnapMetadata struct { SnapMetadata *SNAPPackageMetadata `protobuf:"bytes,23,opt,name=snap_metadata,json=snapMetadata,proto3,oneof"` } -type Inventory_FlatpakMetadata struct { +type Package_FlatpakMetadata struct { FlatpakMetadata *FlatpakPackageMetadata `protobuf:"bytes,24,opt,name=flatpak_metadata,json=flatpakMetadata,proto3,oneof"` } -type Inventory_MacAppsMetadata struct { +type Package_MacAppsMetadata struct { MacAppsMetadata *MacAppsMetadata `protobuf:"bytes,34,opt,name=mac_apps_metadata,json=macAppsMetadata,proto3,oneof"` } -type Inventory_ContainerdRuntimeContainerMetadata struct { +type Package_ContainerdRuntimeContainerMetadata struct { ContainerdRuntimeContainerMetadata *ContainerdRuntimeContainerMetadata `protobuf:"bytes,25,opt,name=containerd_runtime_container_metadata,json=containerdRuntimeContainerMetadata,proto3,oneof"` } -type Inventory_CdxMetadata struct { +type Package_CdxMetadata struct { CdxMetadata *CDXPackageMetadata `protobuf:"bytes,30,opt,name=cdx_metadata,json=cdxMetadata,proto3,oneof"` } -type Inventory_WindowsOsVersionMetadata struct { +type Package_WindowsOsVersionMetadata struct { WindowsOsVersionMetadata *WindowsOSVersion `protobuf:"bytes,33,opt,name=windows_os_version_metadata,json=windowsOsVersionMetadata,proto3,oneof"` } -type Inventory_HomebrewMetadata struct { +type Package_HomebrewMetadata struct { HomebrewMetadata *HomebrewPackageMetadata `protobuf:"bytes,42,opt,name=homebrew_metadata,json=homebrewMetadata,proto3,oneof"` } -func (*Inventory_PythonMetadata) isInventory_Metadata() {} +func (*Package_PythonMetadata) isPackage_Metadata() {} -func (*Inventory_JavascriptMetadata) isInventory_Metadata() {} +func (*Package_JavascriptMetadata) isPackage_Metadata() {} -func (*Inventory_ApkMetadata) isInventory_Metadata() {} +func (*Package_ApkMetadata) isPackage_Metadata() {} -func (*Inventory_DpkgMetadata) isInventory_Metadata() {} +func (*Package_DpkgMetadata) isPackage_Metadata() {} -func (*Inventory_RpmMetadata) isInventory_Metadata() {} +func (*Package_RpmMetadata) isPackage_Metadata() {} -func (*Inventory_CosMetadata) isInventory_Metadata() {} +func (*Package_CosMetadata) isPackage_Metadata() {} -func (*Inventory_DepsjsonMetadata) isInventory_Metadata() {} +func (*Package_DepsjsonMetadata) isPackage_Metadata() {} -func (*Inventory_SpdxMetadata) isInventory_Metadata() {} +func (*Package_SpdxMetadata) isPackage_Metadata() {} -func (*Inventory_JavaArchiveMetadata) isInventory_Metadata() {} +func (*Package_JavaArchiveMetadata) isPackage_Metadata() {} -func (*Inventory_JavaLockfileMetadata) isInventory_Metadata() {} +func (*Package_JavaLockfileMetadata) isPackage_Metadata() {} -func (*Inventory_PacmanMetadata) isInventory_Metadata() {} +func (*Package_PacmanMetadata) isPackage_Metadata() {} -func (*Inventory_NixMetadata) isInventory_Metadata() {} +func (*Package_NixMetadata) isPackage_Metadata() {} -func (*Inventory_KernelModuleMetadata) isInventory_Metadata() {} +func (*Package_KernelModuleMetadata) isPackage_Metadata() {} -func (*Inventory_VmlinuzMetadata) isInventory_Metadata() {} +func (*Package_VmlinuzMetadata) isPackage_Metadata() {} -func (*Inventory_PortageMetadata) isInventory_Metadata() {} +func (*Package_PortageMetadata) isPackage_Metadata() {} -func (*Inventory_OsvMetadata) isInventory_Metadata() {} +func (*Package_OsvMetadata) isPackage_Metadata() {} -func (*Inventory_PythonRequirementsMetadata) isInventory_Metadata() {} +func (*Package_PythonRequirementsMetadata) isPackage_Metadata() {} -func (*Inventory_PythonSetupMetadata) isInventory_Metadata() {} +func (*Package_PythonSetupMetadata) isPackage_Metadata() {} -func (*Inventory_ContainerdContainerMetadata) isInventory_Metadata() {} +func (*Package_ContainerdContainerMetadata) isPackage_Metadata() {} -func (*Inventory_SnapMetadata) isInventory_Metadata() {} +func (*Package_SnapMetadata) isPackage_Metadata() {} -func (*Inventory_FlatpakMetadata) isInventory_Metadata() {} +func (*Package_FlatpakMetadata) isPackage_Metadata() {} -func (*Inventory_MacAppsMetadata) isInventory_Metadata() {} +func (*Package_MacAppsMetadata) isPackage_Metadata() {} -func (*Inventory_ContainerdRuntimeContainerMetadata) isInventory_Metadata() {} +func (*Package_ContainerdRuntimeContainerMetadata) isPackage_Metadata() {} -func (*Inventory_CdxMetadata) isInventory_Metadata() {} +func (*Package_CdxMetadata) isPackage_Metadata() {} -func (*Inventory_WindowsOsVersionMetadata) isInventory_Metadata() {} +func (*Package_WindowsOsVersionMetadata) isPackage_Metadata() {} -func (*Inventory_HomebrewMetadata) isInventory_Metadata() {} +func (*Package_HomebrewMetadata) isPackage_Metadata() {} // Additional identifiers for source code software packages (e.g. NPM). type SourceCodeIdentifier struct { @@ -972,7 +1040,7 @@ type SourceCodeIdentifier struct { func (x *SourceCodeIdentifier) Reset() { *x = SourceCodeIdentifier{} - mi := &file_proto_scan_result_proto_msgTypes[4] + mi := &file_proto_scan_result_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -984,7 +1052,7 @@ func (x *SourceCodeIdentifier) String() string { func (*SourceCodeIdentifier) ProtoMessage() {} func (x *SourceCodeIdentifier) ProtoReflect() protoreflect.Message { - mi := &file_proto_scan_result_proto_msgTypes[4] + mi := &file_proto_scan_result_proto_msgTypes[5] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -997,7 +1065,7 @@ func (x *SourceCodeIdentifier) ProtoReflect() protoreflect.Message { // Deprecated: Use SourceCodeIdentifier.ProtoReflect.Descriptor instead. func (*SourceCodeIdentifier) Descriptor() ([]byte, []int) { - return file_proto_scan_result_proto_rawDescGZIP(), []int{4} + return file_proto_scan_result_proto_rawDescGZIP(), []int{5} } func (x *SourceCodeIdentifier) GetRepo() string { @@ -1033,7 +1101,7 @@ type LayerDetails struct { func (x *LayerDetails) Reset() { *x = LayerDetails{} - mi := &file_proto_scan_result_proto_msgTypes[5] + mi := &file_proto_scan_result_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1045,7 +1113,7 @@ func (x *LayerDetails) String() string { func (*LayerDetails) ProtoMessage() {} func (x *LayerDetails) ProtoReflect() protoreflect.Message { - mi := &file_proto_scan_result_proto_msgTypes[5] + mi := &file_proto_scan_result_proto_msgTypes[6] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1058,7 +1126,7 @@ func (x *LayerDetails) ProtoReflect() protoreflect.Message { // Deprecated: Use LayerDetails.ProtoReflect.Descriptor instead. func (*LayerDetails) Descriptor() ([]byte, []int) { - return file_proto_scan_result_proto_rawDescGZIP(), []int{5} + return file_proto_scan_result_proto_rawDescGZIP(), []int{6} } func (x *LayerDetails) GetIndex() int32 { @@ -1113,7 +1181,7 @@ type Purl struct { func (x *Purl) Reset() { *x = Purl{} - mi := &file_proto_scan_result_proto_msgTypes[6] + mi := &file_proto_scan_result_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1125,7 +1193,7 @@ func (x *Purl) String() string { func (*Purl) ProtoMessage() {} func (x *Purl) ProtoReflect() protoreflect.Message { - mi := &file_proto_scan_result_proto_msgTypes[6] + mi := &file_proto_scan_result_proto_msgTypes[7] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1138,7 +1206,7 @@ func (x *Purl) ProtoReflect() protoreflect.Message { // Deprecated: Use Purl.ProtoReflect.Descriptor instead. func (*Purl) Descriptor() ([]byte, []int) { - return file_proto_scan_result_proto_rawDescGZIP(), []int{6} + return file_proto_scan_result_proto_rawDescGZIP(), []int{7} } func (x *Purl) GetPurl() string { @@ -1201,7 +1269,7 @@ type Qualifier struct { func (x *Qualifier) Reset() { *x = Qualifier{} - mi := &file_proto_scan_result_proto_msgTypes[7] + mi := &file_proto_scan_result_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1213,7 +1281,7 @@ func (x *Qualifier) String() string { func (*Qualifier) ProtoMessage() {} func (x *Qualifier) ProtoReflect() protoreflect.Message { - mi := &file_proto_scan_result_proto_msgTypes[7] + mi := &file_proto_scan_result_proto_msgTypes[8] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1226,7 +1294,7 @@ func (x *Qualifier) ProtoReflect() protoreflect.Message { // Deprecated: Use Qualifier.ProtoReflect.Descriptor instead. func (*Qualifier) Descriptor() ([]byte, []int) { - return file_proto_scan_result_proto_rawDescGZIP(), []int{7} + return file_proto_scan_result_proto_rawDescGZIP(), []int{8} } func (x *Qualifier) GetKey() string { @@ -1263,7 +1331,7 @@ type Finding struct { func (x *Finding) Reset() { *x = Finding{} - mi := &file_proto_scan_result_proto_msgTypes[8] + mi := &file_proto_scan_result_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1275,7 +1343,7 @@ func (x *Finding) String() string { func (*Finding) ProtoMessage() {} func (x *Finding) ProtoReflect() protoreflect.Message { - mi := &file_proto_scan_result_proto_msgTypes[8] + mi := &file_proto_scan_result_proto_msgTypes[9] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1288,7 +1356,7 @@ func (x *Finding) ProtoReflect() protoreflect.Message { // Deprecated: Use Finding.ProtoReflect.Descriptor instead. func (*Finding) Descriptor() ([]byte, []int) { - return file_proto_scan_result_proto_rawDescGZIP(), []int{8} + return file_proto_scan_result_proto_rawDescGZIP(), []int{9} } func (x *Finding) GetAdv() *Advisory { @@ -1336,7 +1404,7 @@ type Advisory struct { func (x *Advisory) Reset() { *x = Advisory{} - mi := &file_proto_scan_result_proto_msgTypes[9] + mi := &file_proto_scan_result_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1348,7 +1416,7 @@ func (x *Advisory) String() string { func (*Advisory) ProtoMessage() {} func (x *Advisory) ProtoReflect() protoreflect.Message { - mi := &file_proto_scan_result_proto_msgTypes[9] + mi := &file_proto_scan_result_proto_msgTypes[10] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1361,7 +1429,7 @@ func (x *Advisory) ProtoReflect() protoreflect.Message { // Deprecated: Use Advisory.ProtoReflect.Descriptor instead. func (*Advisory) Descriptor() ([]byte, []int) { - return file_proto_scan_result_proto_rawDescGZIP(), []int{9} + return file_proto_scan_result_proto_rawDescGZIP(), []int{10} } func (x *Advisory) GetId() *AdvisoryId { @@ -1418,7 +1486,7 @@ type AdvisoryId struct { func (x *AdvisoryId) Reset() { *x = AdvisoryId{} - mi := &file_proto_scan_result_proto_msgTypes[10] + mi := &file_proto_scan_result_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1430,7 +1498,7 @@ func (x *AdvisoryId) String() string { func (*AdvisoryId) ProtoMessage() {} func (x *AdvisoryId) ProtoReflect() protoreflect.Message { - mi := &file_proto_scan_result_proto_msgTypes[10] + mi := &file_proto_scan_result_proto_msgTypes[11] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1443,7 +1511,7 @@ func (x *AdvisoryId) ProtoReflect() protoreflect.Message { // Deprecated: Use AdvisoryId.ProtoReflect.Descriptor instead. func (*AdvisoryId) Descriptor() ([]byte, []int) { - return file_proto_scan_result_proto_rawDescGZIP(), []int{10} + return file_proto_scan_result_proto_rawDescGZIP(), []int{11} } func (x *AdvisoryId) GetPublisher() string { @@ -1474,7 +1542,7 @@ type Severity struct { func (x *Severity) Reset() { *x = Severity{} - mi := &file_proto_scan_result_proto_msgTypes[11] + mi := &file_proto_scan_result_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1486,7 +1554,7 @@ func (x *Severity) String() string { func (*Severity) ProtoMessage() {} func (x *Severity) ProtoReflect() protoreflect.Message { - mi := &file_proto_scan_result_proto_msgTypes[11] + mi := &file_proto_scan_result_proto_msgTypes[12] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1499,7 +1567,7 @@ func (x *Severity) ProtoReflect() protoreflect.Message { // Deprecated: Use Severity.ProtoReflect.Descriptor instead. func (*Severity) Descriptor() ([]byte, []int) { - return file_proto_scan_result_proto_rawDescGZIP(), []int{11} + return file_proto_scan_result_proto_rawDescGZIP(), []int{12} } func (x *Severity) GetSeverity() Severity_SeverityEnum { @@ -1535,7 +1603,7 @@ type CVSS struct { func (x *CVSS) Reset() { *x = CVSS{} - mi := &file_proto_scan_result_proto_msgTypes[12] + mi := &file_proto_scan_result_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1547,7 +1615,7 @@ func (x *CVSS) String() string { func (*CVSS) ProtoMessage() {} func (x *CVSS) ProtoReflect() protoreflect.Message { - mi := &file_proto_scan_result_proto_msgTypes[12] + mi := &file_proto_scan_result_proto_msgTypes[13] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1560,7 +1628,7 @@ func (x *CVSS) ProtoReflect() protoreflect.Message { // Deprecated: Use CVSS.ProtoReflect.Descriptor instead. func (*CVSS) Descriptor() ([]byte, []int) { - return file_proto_scan_result_proto_rawDescGZIP(), []int{12} + return file_proto_scan_result_proto_rawDescGZIP(), []int{13} } func (x *CVSS) GetBaseScore() float32 { @@ -1590,15 +1658,15 @@ type TargetDetails struct { unknownFields protoimpl.UnknownFields // The software affected by the finding. - Inventory *Inventory `protobuf:"bytes,1,opt,name=inventory,proto3" json:"inventory,omitempty"` - // Location of vulnerable files not related to the inventory, + Package *Package `protobuf:"bytes,1,opt,name=package,proto3" json:"package,omitempty"` + // Location of vulnerable files not related to the package, // e.g. config files with misconfigurations. Location []string `protobuf:"bytes,3,rep,name=location,proto3" json:"location,omitempty"` } func (x *TargetDetails) Reset() { *x = TargetDetails{} - mi := &file_proto_scan_result_proto_msgTypes[13] + mi := &file_proto_scan_result_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1610,7 +1678,7 @@ func (x *TargetDetails) String() string { func (*TargetDetails) ProtoMessage() {} func (x *TargetDetails) ProtoReflect() protoreflect.Message { - mi := &file_proto_scan_result_proto_msgTypes[13] + mi := &file_proto_scan_result_proto_msgTypes[14] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1623,12 +1691,12 @@ func (x *TargetDetails) ProtoReflect() protoreflect.Message { // Deprecated: Use TargetDetails.ProtoReflect.Descriptor instead. func (*TargetDetails) Descriptor() ([]byte, []int) { - return file_proto_scan_result_proto_rawDescGZIP(), []int{13} + return file_proto_scan_result_proto_rawDescGZIP(), []int{14} } -func (x *TargetDetails) GetInventory() *Inventory { +func (x *TargetDetails) GetPackage() *Package { if x != nil { - return x.Inventory + return x.Package } return nil } @@ -1652,7 +1720,7 @@ type PythonPackageMetadata struct { func (x *PythonPackageMetadata) Reset() { *x = PythonPackageMetadata{} - mi := &file_proto_scan_result_proto_msgTypes[14] + mi := &file_proto_scan_result_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1664,7 +1732,7 @@ func (x *PythonPackageMetadata) String() string { func (*PythonPackageMetadata) ProtoMessage() {} func (x *PythonPackageMetadata) ProtoReflect() protoreflect.Message { - mi := &file_proto_scan_result_proto_msgTypes[14] + mi := &file_proto_scan_result_proto_msgTypes[15] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1677,7 +1745,7 @@ func (x *PythonPackageMetadata) ProtoReflect() protoreflect.Message { // Deprecated: Use PythonPackageMetadata.ProtoReflect.Descriptor instead. func (*PythonPackageMetadata) Descriptor() ([]byte, []int) { - return file_proto_scan_result_proto_rawDescGZIP(), []int{14} + return file_proto_scan_result_proto_rawDescGZIP(), []int{15} } func (x *PythonPackageMetadata) GetAuthor() string { @@ -1707,7 +1775,7 @@ type JavascriptPackageJSONMetadata struct { func (x *JavascriptPackageJSONMetadata) Reset() { *x = JavascriptPackageJSONMetadata{} - mi := &file_proto_scan_result_proto_msgTypes[15] + mi := &file_proto_scan_result_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1719,7 +1787,7 @@ func (x *JavascriptPackageJSONMetadata) String() string { func (*JavascriptPackageJSONMetadata) ProtoMessage() {} func (x *JavascriptPackageJSONMetadata) ProtoReflect() protoreflect.Message { - mi := &file_proto_scan_result_proto_msgTypes[15] + mi := &file_proto_scan_result_proto_msgTypes[16] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1732,7 +1800,7 @@ func (x *JavascriptPackageJSONMetadata) ProtoReflect() protoreflect.Message { // Deprecated: Use JavascriptPackageJSONMetadata.ProtoReflect.Descriptor instead. func (*JavascriptPackageJSONMetadata) Descriptor() ([]byte, []int) { - return file_proto_scan_result_proto_rawDescGZIP(), []int{15} + return file_proto_scan_result_proto_rawDescGZIP(), []int{16} } func (x *JavascriptPackageJSONMetadata) GetAuthor() string { @@ -1773,7 +1841,7 @@ type APKPackageMetadata struct { func (x *APKPackageMetadata) Reset() { *x = APKPackageMetadata{} - mi := &file_proto_scan_result_proto_msgTypes[16] + mi := &file_proto_scan_result_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1785,7 +1853,7 @@ func (x *APKPackageMetadata) String() string { func (*APKPackageMetadata) ProtoMessage() {} func (x *APKPackageMetadata) ProtoReflect() protoreflect.Message { - mi := &file_proto_scan_result_proto_msgTypes[16] + mi := &file_proto_scan_result_proto_msgTypes[17] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1798,7 +1866,7 @@ func (x *APKPackageMetadata) ProtoReflect() protoreflect.Message { // Deprecated: Use APKPackageMetadata.ProtoReflect.Descriptor instead. func (*APKPackageMetadata) Descriptor() ([]byte, []int) { - return file_proto_scan_result_proto_rawDescGZIP(), []int{16} + return file_proto_scan_result_proto_rawDescGZIP(), []int{17} } func (x *APKPackageMetadata) GetPackageName() string { @@ -1871,7 +1939,7 @@ type DPKGPackageMetadata struct { func (x *DPKGPackageMetadata) Reset() { *x = DPKGPackageMetadata{} - mi := &file_proto_scan_result_proto_msgTypes[17] + mi := &file_proto_scan_result_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1883,7 +1951,7 @@ func (x *DPKGPackageMetadata) String() string { func (*DPKGPackageMetadata) ProtoMessage() {} func (x *DPKGPackageMetadata) ProtoReflect() protoreflect.Message { - mi := &file_proto_scan_result_proto_msgTypes[17] + mi := &file_proto_scan_result_proto_msgTypes[18] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1896,7 +1964,7 @@ func (x *DPKGPackageMetadata) ProtoReflect() protoreflect.Message { // Deprecated: Use DPKGPackageMetadata.ProtoReflect.Descriptor instead. func (*DPKGPackageMetadata) Descriptor() ([]byte, []int) { - return file_proto_scan_result_proto_rawDescGZIP(), []int{17} + return file_proto_scan_result_proto_rawDescGZIP(), []int{18} } func (x *DPKGPackageMetadata) GetPackageName() string { @@ -1989,7 +2057,7 @@ type RPMPackageMetadata struct { func (x *RPMPackageMetadata) Reset() { *x = RPMPackageMetadata{} - mi := &file_proto_scan_result_proto_msgTypes[18] + mi := &file_proto_scan_result_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2001,7 +2069,7 @@ func (x *RPMPackageMetadata) String() string { func (*RPMPackageMetadata) ProtoMessage() {} func (x *RPMPackageMetadata) ProtoReflect() protoreflect.Message { - mi := &file_proto_scan_result_proto_msgTypes[18] + mi := &file_proto_scan_result_proto_msgTypes[19] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2014,7 +2082,7 @@ func (x *RPMPackageMetadata) ProtoReflect() protoreflect.Message { // Deprecated: Use RPMPackageMetadata.ProtoReflect.Descriptor instead. func (*RPMPackageMetadata) Descriptor() ([]byte, []int) { - return file_proto_scan_result_proto_rawDescGZIP(), []int{18} + return file_proto_scan_result_proto_rawDescGZIP(), []int{19} } func (x *RPMPackageMetadata) GetPackageName() string { @@ -2102,7 +2170,7 @@ type COSPackageMetadata struct { func (x *COSPackageMetadata) Reset() { *x = COSPackageMetadata{} - mi := &file_proto_scan_result_proto_msgTypes[19] + mi := &file_proto_scan_result_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2114,7 +2182,7 @@ func (x *COSPackageMetadata) String() string { func (*COSPackageMetadata) ProtoMessage() {} func (x *COSPackageMetadata) ProtoReflect() protoreflect.Message { - mi := &file_proto_scan_result_proto_msgTypes[19] + mi := &file_proto_scan_result_proto_msgTypes[20] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2127,7 +2195,7 @@ func (x *COSPackageMetadata) ProtoReflect() protoreflect.Message { // Deprecated: Use COSPackageMetadata.ProtoReflect.Descriptor instead. func (*COSPackageMetadata) Descriptor() ([]byte, []int) { - return file_proto_scan_result_proto_rawDescGZIP(), []int{19} + return file_proto_scan_result_proto_rawDescGZIP(), []int{20} } func (x *COSPackageMetadata) GetName() string { @@ -2181,7 +2249,7 @@ type PACMANPackageMetadata struct { func (x *PACMANPackageMetadata) Reset() { *x = PACMANPackageMetadata{} - mi := &file_proto_scan_result_proto_msgTypes[20] + mi := &file_proto_scan_result_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2193,7 +2261,7 @@ func (x *PACMANPackageMetadata) String() string { func (*PACMANPackageMetadata) ProtoMessage() {} func (x *PACMANPackageMetadata) ProtoReflect() protoreflect.Message { - mi := &file_proto_scan_result_proto_msgTypes[20] + mi := &file_proto_scan_result_proto_msgTypes[21] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2206,7 +2274,7 @@ func (x *PACMANPackageMetadata) ProtoReflect() protoreflect.Message { // Deprecated: Use PACMANPackageMetadata.ProtoReflect.Descriptor instead. func (*PACMANPackageMetadata) Descriptor() ([]byte, []int) { - return file_proto_scan_result_proto_rawDescGZIP(), []int{20} + return file_proto_scan_result_proto_rawDescGZIP(), []int{21} } func (x *PACMANPackageMetadata) GetPackageName() string { @@ -2268,7 +2336,7 @@ type NixPackageMetadata struct { func (x *NixPackageMetadata) Reset() { *x = NixPackageMetadata{} - mi := &file_proto_scan_result_proto_msgTypes[21] + mi := &file_proto_scan_result_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2280,7 +2348,7 @@ func (x *NixPackageMetadata) String() string { func (*NixPackageMetadata) ProtoMessage() {} func (x *NixPackageMetadata) ProtoReflect() protoreflect.Message { - mi := &file_proto_scan_result_proto_msgTypes[21] + mi := &file_proto_scan_result_proto_msgTypes[22] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2293,7 +2361,7 @@ func (x *NixPackageMetadata) ProtoReflect() protoreflect.Message { // Deprecated: Use NixPackageMetadata.ProtoReflect.Descriptor instead. func (*NixPackageMetadata) Descriptor() ([]byte, []int) { - return file_proto_scan_result_proto_rawDescGZIP(), []int{21} + return file_proto_scan_result_proto_rawDescGZIP(), []int{22} } func (x *NixPackageMetadata) GetPackageName() string { @@ -2358,7 +2426,7 @@ type DEPSJSONMetadata struct { func (x *DEPSJSONMetadata) Reset() { *x = DEPSJSONMetadata{} - mi := &file_proto_scan_result_proto_msgTypes[22] + mi := &file_proto_scan_result_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2370,7 +2438,7 @@ func (x *DEPSJSONMetadata) String() string { func (*DEPSJSONMetadata) ProtoMessage() {} func (x *DEPSJSONMetadata) ProtoReflect() protoreflect.Message { - mi := &file_proto_scan_result_proto_msgTypes[22] + mi := &file_proto_scan_result_proto_msgTypes[23] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2383,7 +2451,7 @@ func (x *DEPSJSONMetadata) ProtoReflect() protoreflect.Message { // Deprecated: Use DEPSJSONMetadata.ProtoReflect.Descriptor instead. func (*DEPSJSONMetadata) Descriptor() ([]byte, []int) { - return file_proto_scan_result_proto_rawDescGZIP(), []int{22} + return file_proto_scan_result_proto_rawDescGZIP(), []int{23} } func (x *DEPSJSONMetadata) GetPackageName() string { @@ -2425,7 +2493,7 @@ type SNAPPackageMetadata struct { func (x *SNAPPackageMetadata) Reset() { *x = SNAPPackageMetadata{} - mi := &file_proto_scan_result_proto_msgTypes[23] + mi := &file_proto_scan_result_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2437,7 +2505,7 @@ func (x *SNAPPackageMetadata) String() string { func (*SNAPPackageMetadata) ProtoMessage() {} func (x *SNAPPackageMetadata) ProtoReflect() protoreflect.Message { - mi := &file_proto_scan_result_proto_msgTypes[23] + mi := &file_proto_scan_result_proto_msgTypes[24] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2450,7 +2518,7 @@ func (x *SNAPPackageMetadata) ProtoReflect() protoreflect.Message { // Deprecated: Use SNAPPackageMetadata.ProtoReflect.Descriptor instead. func (*SNAPPackageMetadata) Descriptor() ([]byte, []int) { - return file_proto_scan_result_proto_rawDescGZIP(), []int{23} + return file_proto_scan_result_proto_rawDescGZIP(), []int{24} } func (x *SNAPPackageMetadata) GetName() string { @@ -2523,7 +2591,7 @@ type PortagePackageMetadata struct { func (x *PortagePackageMetadata) Reset() { *x = PortagePackageMetadata{} - mi := &file_proto_scan_result_proto_msgTypes[24] + mi := &file_proto_scan_result_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2535,7 +2603,7 @@ func (x *PortagePackageMetadata) String() string { func (*PortagePackageMetadata) ProtoMessage() {} func (x *PortagePackageMetadata) ProtoReflect() protoreflect.Message { - mi := &file_proto_scan_result_proto_msgTypes[24] + mi := &file_proto_scan_result_proto_msgTypes[25] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2548,7 +2616,7 @@ func (x *PortagePackageMetadata) ProtoReflect() protoreflect.Message { // Deprecated: Use PortagePackageMetadata.ProtoReflect.Descriptor instead. func (*PortagePackageMetadata) Descriptor() ([]byte, []int) { - return file_proto_scan_result_proto_rawDescGZIP(), []int{24} + return file_proto_scan_result_proto_rawDescGZIP(), []int{25} } func (x *PortagePackageMetadata) GetPackageName() string { @@ -2598,7 +2666,7 @@ type FlatpakPackageMetadata struct { func (x *FlatpakPackageMetadata) Reset() { *x = FlatpakPackageMetadata{} - mi := &file_proto_scan_result_proto_msgTypes[25] + mi := &file_proto_scan_result_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2610,7 +2678,7 @@ func (x *FlatpakPackageMetadata) String() string { func (*FlatpakPackageMetadata) ProtoMessage() {} func (x *FlatpakPackageMetadata) ProtoReflect() protoreflect.Message { - mi := &file_proto_scan_result_proto_msgTypes[25] + mi := &file_proto_scan_result_proto_msgTypes[26] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2623,7 +2691,7 @@ func (x *FlatpakPackageMetadata) ProtoReflect() protoreflect.Message { // Deprecated: Use FlatpakPackageMetadata.ProtoReflect.Descriptor instead. func (*FlatpakPackageMetadata) Descriptor() ([]byte, []int) { - return file_proto_scan_result_proto_rawDescGZIP(), []int{25} + return file_proto_scan_result_proto_rawDescGZIP(), []int{26} } func (x *FlatpakPackageMetadata) GetPackageName() string { @@ -2707,7 +2775,7 @@ type KernelModuleMetadata struct { func (x *KernelModuleMetadata) Reset() { *x = KernelModuleMetadata{} - mi := &file_proto_scan_result_proto_msgTypes[26] + mi := &file_proto_scan_result_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2719,7 +2787,7 @@ func (x *KernelModuleMetadata) String() string { func (*KernelModuleMetadata) ProtoMessage() {} func (x *KernelModuleMetadata) ProtoReflect() protoreflect.Message { - mi := &file_proto_scan_result_proto_msgTypes[26] + mi := &file_proto_scan_result_proto_msgTypes[27] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2732,7 +2800,7 @@ func (x *KernelModuleMetadata) ProtoReflect() protoreflect.Message { // Deprecated: Use KernelModuleMetadata.ProtoReflect.Descriptor instead. func (*KernelModuleMetadata) Descriptor() ([]byte, []int) { - return file_proto_scan_result_proto_rawDescGZIP(), []int{26} + return file_proto_scan_result_proto_rawDescGZIP(), []int{27} } func (x *KernelModuleMetadata) GetPackageName() string { @@ -2813,7 +2881,7 @@ type VmlinuzMetadata struct { func (x *VmlinuzMetadata) Reset() { *x = VmlinuzMetadata{} - mi := &file_proto_scan_result_proto_msgTypes[27] + mi := &file_proto_scan_result_proto_msgTypes[28] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2825,7 +2893,7 @@ func (x *VmlinuzMetadata) String() string { func (*VmlinuzMetadata) ProtoMessage() {} func (x *VmlinuzMetadata) ProtoReflect() protoreflect.Message { - mi := &file_proto_scan_result_proto_msgTypes[27] + mi := &file_proto_scan_result_proto_msgTypes[28] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2838,7 +2906,7 @@ func (x *VmlinuzMetadata) ProtoReflect() protoreflect.Message { // Deprecated: Use VmlinuzMetadata.ProtoReflect.Descriptor instead. func (*VmlinuzMetadata) Descriptor() ([]byte, []int) { - return file_proto_scan_result_proto_rawDescGZIP(), []int{27} + return file_proto_scan_result_proto_rawDescGZIP(), []int{28} } func (x *VmlinuzMetadata) GetName() string { @@ -2945,7 +3013,7 @@ type MacAppsMetadata struct { func (x *MacAppsMetadata) Reset() { *x = MacAppsMetadata{} - mi := &file_proto_scan_result_proto_msgTypes[28] + mi := &file_proto_scan_result_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2957,7 +3025,7 @@ func (x *MacAppsMetadata) String() string { func (*MacAppsMetadata) ProtoMessage() {} func (x *MacAppsMetadata) ProtoReflect() protoreflect.Message { - mi := &file_proto_scan_result_proto_msgTypes[28] + mi := &file_proto_scan_result_proto_msgTypes[29] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2970,7 +3038,7 @@ func (x *MacAppsMetadata) ProtoReflect() protoreflect.Message { // Deprecated: Use MacAppsMetadata.ProtoReflect.Descriptor instead. func (*MacAppsMetadata) Descriptor() ([]byte, []int) { - return file_proto_scan_result_proto_rawDescGZIP(), []int{28} + return file_proto_scan_result_proto_rawDescGZIP(), []int{29} } func (x *MacAppsMetadata) GetBundleDisplayName() string { @@ -3055,7 +3123,7 @@ type SPDXPackageMetadata struct { func (x *SPDXPackageMetadata) Reset() { *x = SPDXPackageMetadata{} - mi := &file_proto_scan_result_proto_msgTypes[29] + mi := &file_proto_scan_result_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3067,7 +3135,7 @@ func (x *SPDXPackageMetadata) String() string { func (*SPDXPackageMetadata) ProtoMessage() {} func (x *SPDXPackageMetadata) ProtoReflect() protoreflect.Message { - mi := &file_proto_scan_result_proto_msgTypes[29] + mi := &file_proto_scan_result_proto_msgTypes[30] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3080,7 +3148,7 @@ func (x *SPDXPackageMetadata) ProtoReflect() protoreflect.Message { // Deprecated: Use SPDXPackageMetadata.ProtoReflect.Descriptor instead. func (*SPDXPackageMetadata) Descriptor() ([]byte, []int) { - return file_proto_scan_result_proto_rawDescGZIP(), []int{29} + return file_proto_scan_result_proto_rawDescGZIP(), []int{30} } func (x *SPDXPackageMetadata) GetPurl() *Purl { @@ -3109,7 +3177,7 @@ type CDXPackageMetadata struct { func (x *CDXPackageMetadata) Reset() { *x = CDXPackageMetadata{} - mi := &file_proto_scan_result_proto_msgTypes[30] + mi := &file_proto_scan_result_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3121,7 +3189,7 @@ func (x *CDXPackageMetadata) String() string { func (*CDXPackageMetadata) ProtoMessage() {} func (x *CDXPackageMetadata) ProtoReflect() protoreflect.Message { - mi := &file_proto_scan_result_proto_msgTypes[30] + mi := &file_proto_scan_result_proto_msgTypes[31] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3134,7 +3202,7 @@ func (x *CDXPackageMetadata) ProtoReflect() protoreflect.Message { // Deprecated: Use CDXPackageMetadata.ProtoReflect.Descriptor instead. func (*CDXPackageMetadata) Descriptor() ([]byte, []int) { - return file_proto_scan_result_proto_rawDescGZIP(), []int{30} + return file_proto_scan_result_proto_rawDescGZIP(), []int{31} } func (x *CDXPackageMetadata) GetPurl() *Purl { @@ -3164,7 +3232,7 @@ type JavaArchiveMetadata struct { func (x *JavaArchiveMetadata) Reset() { *x = JavaArchiveMetadata{} - mi := &file_proto_scan_result_proto_msgTypes[31] + mi := &file_proto_scan_result_proto_msgTypes[32] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3176,7 +3244,7 @@ func (x *JavaArchiveMetadata) String() string { func (*JavaArchiveMetadata) ProtoMessage() {} func (x *JavaArchiveMetadata) ProtoReflect() protoreflect.Message { - mi := &file_proto_scan_result_proto_msgTypes[31] + mi := &file_proto_scan_result_proto_msgTypes[32] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3189,7 +3257,7 @@ func (x *JavaArchiveMetadata) ProtoReflect() protoreflect.Message { // Deprecated: Use JavaArchiveMetadata.ProtoReflect.Descriptor instead. func (*JavaArchiveMetadata) Descriptor() ([]byte, []int) { - return file_proto_scan_result_proto_rawDescGZIP(), []int{31} + return file_proto_scan_result_proto_rawDescGZIP(), []int{32} } func (x *JavaArchiveMetadata) GetArtifactId() string { @@ -3226,7 +3294,7 @@ type JavaLockfileMetadata struct { func (x *JavaLockfileMetadata) Reset() { *x = JavaLockfileMetadata{} - mi := &file_proto_scan_result_proto_msgTypes[32] + mi := &file_proto_scan_result_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3238,7 +3306,7 @@ func (x *JavaLockfileMetadata) String() string { func (*JavaLockfileMetadata) ProtoMessage() {} func (x *JavaLockfileMetadata) ProtoReflect() protoreflect.Message { - mi := &file_proto_scan_result_proto_msgTypes[32] + mi := &file_proto_scan_result_proto_msgTypes[33] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3251,7 +3319,7 @@ func (x *JavaLockfileMetadata) ProtoReflect() protoreflect.Message { // Deprecated: Use JavaLockfileMetadata.ProtoReflect.Descriptor instead. func (*JavaLockfileMetadata) Descriptor() ([]byte, []int) { - return file_proto_scan_result_proto_rawDescGZIP(), []int{32} + return file_proto_scan_result_proto_rawDescGZIP(), []int{33} } func (x *JavaLockfileMetadata) GetArtifactId() string { @@ -3289,7 +3357,7 @@ type OSVPackageMetadata struct { func (x *OSVPackageMetadata) Reset() { *x = OSVPackageMetadata{} - mi := &file_proto_scan_result_proto_msgTypes[33] + mi := &file_proto_scan_result_proto_msgTypes[34] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3301,7 +3369,7 @@ func (x *OSVPackageMetadata) String() string { func (*OSVPackageMetadata) ProtoMessage() {} func (x *OSVPackageMetadata) ProtoReflect() protoreflect.Message { - mi := &file_proto_scan_result_proto_msgTypes[33] + mi := &file_proto_scan_result_proto_msgTypes[34] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3314,7 +3382,7 @@ func (x *OSVPackageMetadata) ProtoReflect() protoreflect.Message { // Deprecated: Use OSVPackageMetadata.ProtoReflect.Descriptor instead. func (*OSVPackageMetadata) Descriptor() ([]byte, []int) { - return file_proto_scan_result_proto_rawDescGZIP(), []int{33} + return file_proto_scan_result_proto_rawDescGZIP(), []int{34} } func (x *OSVPackageMetadata) GetPurlType() string { @@ -3356,7 +3424,7 @@ type PythonRequirementsMetadata struct { func (x *PythonRequirementsMetadata) Reset() { *x = PythonRequirementsMetadata{} - mi := &file_proto_scan_result_proto_msgTypes[34] + mi := &file_proto_scan_result_proto_msgTypes[35] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3368,7 +3436,7 @@ func (x *PythonRequirementsMetadata) String() string { func (*PythonRequirementsMetadata) ProtoMessage() {} func (x *PythonRequirementsMetadata) ProtoReflect() protoreflect.Message { - mi := &file_proto_scan_result_proto_msgTypes[34] + mi := &file_proto_scan_result_proto_msgTypes[35] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3381,7 +3449,7 @@ func (x *PythonRequirementsMetadata) ProtoReflect() protoreflect.Message { // Deprecated: Use PythonRequirementsMetadata.ProtoReflect.Descriptor instead. func (*PythonRequirementsMetadata) Descriptor() ([]byte, []int) { - return file_proto_scan_result_proto_rawDescGZIP(), []int{34} + return file_proto_scan_result_proto_rawDescGZIP(), []int{35} } func (x *PythonRequirementsMetadata) GetHashCheckingModeValues() []string { @@ -3408,7 +3476,7 @@ type PythonSetupMetadata struct { func (x *PythonSetupMetadata) Reset() { *x = PythonSetupMetadata{} - mi := &file_proto_scan_result_proto_msgTypes[35] + mi := &file_proto_scan_result_proto_msgTypes[36] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3420,7 +3488,7 @@ func (x *PythonSetupMetadata) String() string { func (*PythonSetupMetadata) ProtoMessage() {} func (x *PythonSetupMetadata) ProtoReflect() protoreflect.Message { - mi := &file_proto_scan_result_proto_msgTypes[35] + mi := &file_proto_scan_result_proto_msgTypes[36] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3433,7 +3501,7 @@ func (x *PythonSetupMetadata) ProtoReflect() protoreflect.Message { // Deprecated: Use PythonSetupMetadata.ProtoReflect.Descriptor instead. func (*PythonSetupMetadata) Descriptor() ([]byte, []int) { - return file_proto_scan_result_proto_rawDescGZIP(), []int{35} + return file_proto_scan_result_proto_rawDescGZIP(), []int{36} } func (x *PythonSetupMetadata) GetVersionComparator() string { @@ -3464,7 +3532,7 @@ type ContainerdContainerMetadata struct { func (x *ContainerdContainerMetadata) Reset() { *x = ContainerdContainerMetadata{} - mi := &file_proto_scan_result_proto_msgTypes[36] + mi := &file_proto_scan_result_proto_msgTypes[37] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3476,7 +3544,7 @@ func (x *ContainerdContainerMetadata) String() string { func (*ContainerdContainerMetadata) ProtoMessage() {} func (x *ContainerdContainerMetadata) ProtoReflect() protoreflect.Message { - mi := &file_proto_scan_result_proto_msgTypes[36] + mi := &file_proto_scan_result_proto_msgTypes[37] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3489,7 +3557,7 @@ func (x *ContainerdContainerMetadata) ProtoReflect() protoreflect.Message { // Deprecated: Use ContainerdContainerMetadata.ProtoReflect.Descriptor instead. func (*ContainerdContainerMetadata) Descriptor() ([]byte, []int) { - return file_proto_scan_result_proto_rawDescGZIP(), []int{36} + return file_proto_scan_result_proto_rawDescGZIP(), []int{37} } func (x *ContainerdContainerMetadata) GetNamespaceName() string { @@ -3592,7 +3660,7 @@ type ContainerdRuntimeContainerMetadata struct { func (x *ContainerdRuntimeContainerMetadata) Reset() { *x = ContainerdRuntimeContainerMetadata{} - mi := &file_proto_scan_result_proto_msgTypes[37] + mi := &file_proto_scan_result_proto_msgTypes[38] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3604,7 +3672,7 @@ func (x *ContainerdRuntimeContainerMetadata) String() string { func (*ContainerdRuntimeContainerMetadata) ProtoMessage() {} func (x *ContainerdRuntimeContainerMetadata) ProtoReflect() protoreflect.Message { - mi := &file_proto_scan_result_proto_msgTypes[37] + mi := &file_proto_scan_result_proto_msgTypes[38] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3617,7 +3685,7 @@ func (x *ContainerdRuntimeContainerMetadata) ProtoReflect() protoreflect.Message // Deprecated: Use ContainerdRuntimeContainerMetadata.ProtoReflect.Descriptor instead. func (*ContainerdRuntimeContainerMetadata) Descriptor() ([]byte, []int) { - return file_proto_scan_result_proto_rawDescGZIP(), []int{37} + return file_proto_scan_result_proto_rawDescGZIP(), []int{38} } func (x *ContainerdRuntimeContainerMetadata) GetNamespaceName() string { @@ -3680,7 +3748,7 @@ type WindowsOSVersion struct { func (x *WindowsOSVersion) Reset() { *x = WindowsOSVersion{} - mi := &file_proto_scan_result_proto_msgTypes[38] + mi := &file_proto_scan_result_proto_msgTypes[39] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3692,7 +3760,7 @@ func (x *WindowsOSVersion) String() string { func (*WindowsOSVersion) ProtoMessage() {} func (x *WindowsOSVersion) ProtoReflect() protoreflect.Message { - mi := &file_proto_scan_result_proto_msgTypes[38] + mi := &file_proto_scan_result_proto_msgTypes[39] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3705,7 +3773,7 @@ func (x *WindowsOSVersion) ProtoReflect() protoreflect.Message { // Deprecated: Use WindowsOSVersion.ProtoReflect.Descriptor instead. func (*WindowsOSVersion) Descriptor() ([]byte, []int) { - return file_proto_scan_result_proto_rawDescGZIP(), []int{38} + return file_proto_scan_result_proto_rawDescGZIP(), []int{39} } func (x *WindowsOSVersion) GetProduct() string { @@ -3731,7 +3799,7 @@ type HomebrewPackageMetadata struct { func (x *HomebrewPackageMetadata) Reset() { *x = HomebrewPackageMetadata{} - mi := &file_proto_scan_result_proto_msgTypes[39] + mi := &file_proto_scan_result_proto_msgTypes[40] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3743,7 +3811,7 @@ func (x *HomebrewPackageMetadata) String() string { func (*HomebrewPackageMetadata) ProtoMessage() {} func (x *HomebrewPackageMetadata) ProtoReflect() protoreflect.Message { - mi := &file_proto_scan_result_proto_msgTypes[39] + mi := &file_proto_scan_result_proto_msgTypes[40] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3756,7 +3824,7 @@ func (x *HomebrewPackageMetadata) ProtoReflect() protoreflect.Message { // Deprecated: Use HomebrewPackageMetadata.ProtoReflect.Descriptor instead. func (*HomebrewPackageMetadata) Descriptor() ([]byte, []int) { - return file_proto_scan_result_proto_rawDescGZIP(), []int{39} + return file_proto_scan_result_proto_rawDescGZIP(), []int{40} } var File_proto_scan_result_proto protoreflect.FileDescriptor @@ -3766,7 +3834,7 @@ var file_proto_scan_result_proto_rawDesc = []byte{ 0x75, 0x6c, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x07, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x22, 0xe5, 0x02, 0x0a, 0x0a, 0x53, 0x63, 0x61, 0x6e, 0x52, 0x65, 0x73, 0x75, + 0x6f, 0x74, 0x6f, 0x22, 0xc7, 0x03, 0x0a, 0x0a, 0x53, 0x63, 0x61, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x39, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, @@ -3782,596 +3850,584 @@ var file_proto_scan_result_proto_rawDesc = []byte{ 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x0c, 0x70, 0x6c, 0x75, 0x67, 0x69, - 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x34, 0x0a, 0x0b, 0x69, 0x6e, 0x76, 0x65, 0x6e, - 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x73, - 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, - 0x52, 0x0b, 0x69, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x12, 0x2c, 0x0a, - 0x08, 0x66, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x10, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x69, 0x6e, - 0x67, 0x52, 0x08, 0x66, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x22, 0xc6, 0x01, 0x0a, 0x0a, - 0x53, 0x63, 0x61, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x3a, 0x0a, 0x06, 0x73, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x22, 0x2e, 0x73, 0x63, 0x61, - 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x53, 0x63, 0x61, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, - 0x53, 0x63, 0x61, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x06, - 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x66, 0x61, 0x69, 0x6c, 0x75, 0x72, - 0x65, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, - 0x66, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0x55, 0x0a, - 0x0e, 0x53, 0x63, 0x61, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x45, 0x6e, 0x75, 0x6d, 0x12, - 0x0f, 0x0a, 0x0b, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, - 0x12, 0x0d, 0x0a, 0x09, 0x53, 0x55, 0x43, 0x43, 0x45, 0x45, 0x44, 0x45, 0x44, 0x10, 0x01, 0x12, - 0x17, 0x0a, 0x13, 0x50, 0x41, 0x52, 0x54, 0x49, 0x41, 0x4c, 0x4c, 0x59, 0x5f, 0x53, 0x55, 0x43, - 0x43, 0x45, 0x45, 0x44, 0x45, 0x44, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x46, 0x41, 0x49, 0x4c, - 0x45, 0x44, 0x10, 0x03, 0x22, 0x69, 0x0a, 0x0c, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x12, 0x2b, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x53, 0x63, 0x61, - 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, - 0x8d, 0x14, 0x0a, 0x09, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x12, 0x0a, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x0c, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, 0x0b, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1d, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, - 0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x21, 0x0a, 0x04, 0x70, - 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x73, 0x63, 0x61, 0x6c, - 0x69, 0x62, 0x72, 0x2e, 0x50, 0x75, 0x72, 0x6c, 0x52, 0x04, 0x70, 0x75, 0x72, 0x6c, 0x12, 0x1c, - 0x0a, 0x09, 0x65, 0x63, 0x6f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x18, 0x1b, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x09, 0x65, 0x63, 0x6f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x1c, 0x0a, 0x09, - 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x65, 0x78, - 0x74, 0x72, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, - 0x78, 0x74, 0x72, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x49, 0x0a, 0x0f, 0x70, 0x79, 0x74, 0x68, - 0x6f, 0x6e, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1e, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x50, 0x79, 0x74, 0x68, - 0x6f, 0x6e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x48, 0x00, 0x52, 0x0e, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0x12, 0x59, 0x0a, 0x13, 0x6a, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x26, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x4a, 0x61, 0x76, 0x61, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4a, 0x53, 0x4f, 0x4e, - 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x12, 0x6a, 0x61, 0x76, 0x61, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x40, - 0x0a, 0x0c, 0x61, 0x70, 0x6b, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x07, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x41, - 0x50, 0x4b, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x48, 0x00, 0x52, 0x0b, 0x61, 0x70, 0x6b, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x12, 0x43, 0x0a, 0x0d, 0x64, 0x70, 0x6b, 0x67, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, - 0x72, 0x2e, 0x44, 0x50, 0x4b, 0x47, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x0c, 0x64, 0x70, 0x6b, 0x67, 0x4d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x40, 0x0a, 0x0c, 0x72, 0x70, 0x6d, 0x5f, 0x6d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x73, 0x63, - 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x52, 0x50, 0x4d, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, - 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x0b, 0x72, 0x70, 0x6d, 0x4d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x40, 0x0a, 0x0c, 0x63, 0x6f, 0x73, 0x5f, 0x6d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, - 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x43, 0x4f, 0x53, 0x50, 0x61, 0x63, 0x6b, 0x61, - 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x0b, 0x63, 0x6f, - 0x73, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x48, 0x0a, 0x11, 0x64, 0x65, 0x70, - 0x73, 0x6a, 0x73, 0x6f, 0x6e, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x28, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x44, - 0x45, 0x50, 0x53, 0x4a, 0x53, 0x4f, 0x4e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, - 0x00, 0x52, 0x10, 0x64, 0x65, 0x70, 0x73, 0x6a, 0x73, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0x12, 0x43, 0x0a, 0x0d, 0x73, 0x70, 0x64, 0x78, 0x5f, 0x6d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x73, 0x63, 0x61, - 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x53, 0x50, 0x44, 0x58, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, - 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x0c, 0x73, 0x70, 0x64, 0x78, - 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x52, 0x0a, 0x15, 0x6a, 0x61, 0x76, 0x61, - 0x5f, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, - 0x72, 0x2e, 0x4a, 0x61, 0x76, 0x61, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x4d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x13, 0x6a, 0x61, 0x76, 0x61, 0x41, 0x72, 0x63, - 0x68, 0x69, 0x76, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x55, 0x0a, 0x16, - 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x6c, 0x6f, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x6d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x73, - 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x4a, 0x61, 0x76, 0x61, 0x4c, 0x6f, 0x63, 0x6b, 0x66, - 0x69, 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x14, 0x6a, - 0x61, 0x76, 0x61, 0x4c, 0x6f, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0x12, 0x49, 0x0a, 0x0f, 0x70, 0x61, 0x63, 0x6d, 0x61, 0x6e, 0x5f, 0x6d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x24, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x73, - 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x50, 0x41, 0x43, 0x4d, 0x41, 0x4e, 0x50, 0x61, 0x63, - 0x6b, 0x61, 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x0e, - 0x70, 0x61, 0x63, 0x6d, 0x61, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x40, - 0x0a, 0x0c, 0x6e, 0x69, 0x78, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x25, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x4e, - 0x69, 0x78, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x48, 0x00, 0x52, 0x0b, 0x6e, 0x69, 0x78, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x12, 0x55, 0x0a, 0x16, 0x6b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, - 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x26, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1d, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x4b, 0x65, 0x72, 0x6e, 0x65, - 0x6c, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, - 0x00, 0x52, 0x14, 0x6b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x4d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x45, 0x0a, 0x10, 0x76, 0x6d, 0x6c, 0x69, 0x6e, - 0x75, 0x7a, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x27, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x18, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x56, 0x6d, 0x6c, 0x69, - 0x6e, 0x75, 0x7a, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x0f, 0x76, - 0x6d, 0x6c, 0x69, 0x6e, 0x75, 0x7a, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x4c, - 0x0a, 0x10, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x67, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x18, 0x29, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, - 0x62, 0x72, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x61, 0x67, 0x65, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, - 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x0f, 0x70, 0x6f, 0x72, - 0x74, 0x61, 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x40, 0x0a, 0x0c, - 0x6f, 0x73, 0x76, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x10, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x4f, 0x53, 0x56, - 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, - 0x00, 0x52, 0x0b, 0x6f, 0x73, 0x76, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x67, - 0x0a, 0x1c, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, - 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x15, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x50, - 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, - 0x73, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x1a, 0x70, 0x79, 0x74, - 0x68, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x4d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x52, 0x0a, 0x15, 0x70, 0x79, 0x74, 0x68, 0x6f, - 0x6e, 0x5f, 0x73, 0x65, 0x74, 0x75, 0x70, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x18, 0x2c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, - 0x2e, 0x50, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x13, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x53, 0x65, - 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x6a, 0x0a, 0x1d, 0x63, - 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, - 0x6e, 0x65, 0x72, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x16, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x43, 0x6f, 0x6e, - 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, - 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x1b, 0x63, 0x6f, 0x6e, 0x74, - 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x4d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x43, 0x0a, 0x0d, 0x73, 0x6e, 0x61, 0x70, 0x5f, - 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x17, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, - 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x53, 0x4e, 0x41, 0x50, 0x50, 0x61, 0x63, - 0x6b, 0x61, 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x0c, - 0x73, 0x6e, 0x61, 0x70, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x4c, 0x0a, 0x10, - 0x66, 0x6c, 0x61, 0x74, 0x70, 0x61, 0x6b, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x18, 0x18, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, - 0x2e, 0x46, 0x6c, 0x61, 0x74, 0x70, 0x61, 0x6b, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x0f, 0x66, 0x6c, 0x61, 0x74, 0x70, - 0x61, 0x6b, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x46, 0x0a, 0x11, 0x6d, 0x61, - 0x63, 0x5f, 0x61, 0x70, 0x70, 0x73, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, - 0x22, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, - 0x4d, 0x61, 0x63, 0x41, 0x70, 0x70, 0x73, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, - 0x00, 0x52, 0x0f, 0x6d, 0x61, 0x63, 0x41, 0x70, 0x70, 0x73, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x12, 0x80, 0x01, 0x0a, 0x25, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, - 0x64, 0x5f, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, - 0x6e, 0x65, 0x72, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x19, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x43, 0x6f, 0x6e, - 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x43, 0x6f, - 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, - 0x00, 0x52, 0x22, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x52, 0x75, 0x6e, - 0x74, 0x69, 0x6d, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x4d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x40, 0x0a, 0x0c, 0x63, 0x64, 0x78, 0x5f, 0x6d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x73, 0x63, - 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x43, 0x44, 0x58, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, - 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x0b, 0x63, 0x64, 0x78, 0x4d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x5a, 0x0a, 0x1b, 0x77, 0x69, 0x6e, 0x64, 0x6f, - 0x77, 0x73, 0x5f, 0x6f, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x21, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x73, - 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x4f, 0x53, - 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x18, 0x77, 0x69, 0x6e, 0x64, 0x6f, - 0x77, 0x73, 0x4f, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0x12, 0x4f, 0x0a, 0x11, 0x68, 0x6f, 0x6d, 0x65, 0x62, 0x72, 0x65, 0x77, 0x5f, - 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x2a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, - 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x48, 0x6f, 0x6d, 0x65, 0x62, 0x72, 0x65, - 0x77, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x48, 0x00, 0x52, 0x10, 0x68, 0x6f, 0x6d, 0x65, 0x62, 0x72, 0x65, 0x77, 0x4d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x12, 0x43, 0x0a, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x18, 0x1c, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x73, 0x63, 0x61, 0x6c, - 0x69, 0x62, 0x72, 0x2e, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0x41, 0x6e, - 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x0b, 0x61, 0x6e, - 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3a, 0x0a, 0x0d, 0x6c, 0x61, 0x79, - 0x65, 0x72, 0x5f, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x23, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x15, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x4c, 0x61, 0x79, 0x65, 0x72, - 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x0c, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x44, 0x65, - 0x74, 0x61, 0x69, 0x6c, 0x73, 0x22, 0x60, 0x0a, 0x0e, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x0f, 0x0a, 0x0b, 0x55, 0x4e, 0x53, 0x50, 0x45, - 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x52, 0x41, 0x4e, - 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x15, 0x0a, 0x11, 0x49, 0x4e, - 0x53, 0x49, 0x44, 0x45, 0x5f, 0x4f, 0x53, 0x5f, 0x50, 0x41, 0x43, 0x4b, 0x41, 0x47, 0x45, 0x10, - 0x02, 0x12, 0x14, 0x0a, 0x10, 0x49, 0x4e, 0x53, 0x49, 0x44, 0x45, 0x5f, 0x43, 0x41, 0x43, 0x48, - 0x45, 0x5f, 0x44, 0x49, 0x52, 0x10, 0x03, 0x42, 0x0a, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x22, - 0x42, 0x0a, 0x14, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x65, - 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x65, 0x70, 0x6f, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x65, 0x70, 0x6f, 0x12, 0x16, 0x0a, 0x06, 0x63, - 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x6f, 0x6d, - 0x6d, 0x69, 0x74, 0x22, 0x7b, 0x0a, 0x0c, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x44, 0x65, 0x74, 0x61, - 0x69, 0x6c, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x69, 0x66, - 0x66, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x69, 0x66, 0x66, - 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x22, 0x0a, 0x0d, - 0x69, 0x6e, 0x5f, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x6e, 0x42, 0x61, 0x73, 0x65, 0x49, 0x6d, 0x61, 0x67, 0x65, - 0x22, 0xc8, 0x01, 0x0a, 0x04, 0x50, 0x75, 0x72, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x75, 0x72, - 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x75, 0x72, 0x6c, 0x12, 0x12, 0x0a, - 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, - 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, - 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x32, 0x0a, - 0x0a, 0x71, 0x75, 0x61, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x72, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x12, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x51, 0x75, 0x61, 0x6c, - 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x0a, 0x71, 0x75, 0x61, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x72, - 0x73, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x62, 0x70, 0x61, 0x74, 0x68, 0x18, 0x07, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x07, 0x73, 0x75, 0x62, 0x70, 0x61, 0x74, 0x68, 0x22, 0x33, 0x0a, 0x09, 0x51, - 0x75, 0x61, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x22, 0x92, 0x01, 0x0a, 0x07, 0x46, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x23, 0x0a, 0x03, - 0x61, 0x64, 0x76, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x73, 0x63, 0x61, 0x6c, - 0x69, 0x62, 0x72, 0x2e, 0x41, 0x64, 0x76, 0x69, 0x73, 0x6f, 0x72, 0x79, 0x52, 0x03, 0x61, 0x64, - 0x76, 0x12, 0x2e, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x16, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x54, 0x61, 0x72, 0x67, - 0x65, 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, - 0x74, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x78, 0x74, 0x72, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x65, 0x78, 0x74, 0x72, 0x61, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x65, 0x74, 0x65, 0x63, - 0x74, 0x6f, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x64, 0x65, 0x74, 0x65, - 0x63, 0x74, 0x6f, 0x72, 0x73, 0x22, 0xa1, 0x02, 0x0a, 0x08, 0x41, 0x64, 0x76, 0x69, 0x73, 0x6f, - 0x72, 0x79, 0x12, 0x23, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, - 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x41, 0x64, 0x76, 0x69, 0x73, 0x6f, 0x72, - 0x79, 0x49, 0x64, 0x52, 0x02, 0x69, 0x64, 0x12, 0x2e, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1a, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, - 0x41, 0x64, 0x76, 0x69, 0x73, 0x6f, 0x72, 0x79, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x45, 0x6e, 0x75, - 0x6d, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x20, 0x0a, - 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x26, 0x0a, 0x0e, 0x72, 0x65, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x65, 0x63, 0x6f, 0x6d, 0x6d, 0x65, - 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x03, 0x73, 0x65, 0x76, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x53, - 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x52, 0x03, 0x73, 0x65, 0x76, 0x22, 0x3b, 0x0a, 0x08, - 0x54, 0x79, 0x70, 0x65, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, - 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x56, 0x55, 0x4c, 0x4e, 0x45, 0x52, 0x41, - 0x42, 0x49, 0x4c, 0x49, 0x54, 0x59, 0x10, 0x01, 0x12, 0x0f, 0x0a, 0x0b, 0x43, 0x49, 0x53, 0x5f, - 0x46, 0x49, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x22, 0x48, 0x0a, 0x0a, 0x41, 0x64, 0x76, - 0x69, 0x73, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, - 0x73, 0x68, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, - 0x69, 0x73, 0x68, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, - 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, - 0x6e, 0x63, 0x65, 0x22, 0xf1, 0x01, 0x0a, 0x08, 0x53, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, - 0x12, 0x3a, 0x0a, 0x08, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0e, 0x32, 0x1e, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x53, 0x65, 0x76, - 0x65, 0x72, 0x69, 0x74, 0x79, 0x2e, 0x53, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x45, 0x6e, - 0x75, 0x6d, 0x52, 0x08, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x12, 0x26, 0x0a, 0x07, - 0x63, 0x76, 0x73, 0x73, 0x5f, 0x76, 0x32, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, - 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x43, 0x56, 0x53, 0x53, 0x52, 0x06, 0x63, 0x76, - 0x73, 0x73, 0x56, 0x32, 0x12, 0x26, 0x0a, 0x07, 0x63, 0x76, 0x73, 0x73, 0x5f, 0x76, 0x33, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, - 0x43, 0x56, 0x53, 0x53, 0x52, 0x06, 0x63, 0x76, 0x73, 0x73, 0x56, 0x33, 0x22, 0x59, 0x0a, 0x0c, - 0x53, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x0f, 0x0a, 0x0b, - 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0b, 0x0a, - 0x07, 0x4d, 0x49, 0x4e, 0x49, 0x4d, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x4c, 0x4f, - 0x57, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x4d, 0x45, 0x44, 0x49, 0x55, 0x4d, 0x10, 0x03, 0x12, - 0x08, 0x0a, 0x04, 0x48, 0x49, 0x47, 0x48, 0x10, 0x04, 0x12, 0x0c, 0x0a, 0x08, 0x43, 0x52, 0x49, - 0x54, 0x49, 0x43, 0x41, 0x4c, 0x10, 0x05, 0x22, 0x7d, 0x0a, 0x04, 0x43, 0x56, 0x53, 0x53, 0x12, - 0x1d, 0x0a, 0x0a, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x02, 0x52, 0x09, 0x62, 0x61, 0x73, 0x65, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x25, - 0x0a, 0x0e, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x6c, 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x02, 0x52, 0x0d, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x6c, - 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x2f, 0x0a, 0x13, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, - 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x02, 0x52, 0x12, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x61, - 0x6c, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x22, 0x5d, 0x0a, 0x0d, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, - 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x30, 0x0a, 0x09, 0x69, 0x6e, 0x76, 0x65, 0x6e, - 0x74, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x73, 0x63, 0x61, - 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x09, - 0x69, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x6f, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x6f, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x52, 0x0a, 0x15, 0x50, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x50, - 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x16, - 0x0a, 0x06, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, - 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x75, - 0x74, 0x68, 0x6f, 0x72, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x22, 0x7d, 0x0a, 0x1d, 0x4a, 0x61, 0x76, - 0x61, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4a, 0x53, - 0x4f, 0x4e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x75, - 0x74, 0x68, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x75, 0x74, 0x68, - 0x6f, 0x72, 0x12, 0x20, 0x0a, 0x0b, 0x6d, 0x61, 0x69, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, - 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x6d, 0x61, 0x69, 0x6e, 0x74, 0x61, 0x69, - 0x6e, 0x65, 0x72, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, - 0x74, 0x6f, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x73, 0x22, 0xef, 0x01, 0x0a, 0x12, 0x41, 0x50, 0x4b, + 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x4b, 0x0a, 0x16, 0x69, 0x6e, 0x76, 0x65, 0x6e, + 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x5f, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, + 0x64, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, + 0x72, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x42, 0x02, 0x18, 0x01, 0x52, 0x15, 0x69, + 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, + 0x61, 0x74, 0x65, 0x64, 0x12, 0x45, 0x0a, 0x13, 0x66, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, + 0x5f, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x07, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x10, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x46, 0x69, 0x6e, 0x64, + 0x69, 0x6e, 0x67, 0x42, 0x02, 0x18, 0x01, 0x52, 0x12, 0x66, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, + 0x73, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x30, 0x0a, 0x09, 0x69, + 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, + 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, + 0x72, 0x79, 0x52, 0x09, 0x69, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x22, 0x67, 0x0a, + 0x09, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x2c, 0x0a, 0x08, 0x70, 0x61, + 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x73, + 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x52, 0x08, + 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x12, 0x2c, 0x0a, 0x08, 0x66, 0x69, 0x6e, 0x64, + 0x69, 0x6e, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x73, 0x63, 0x61, + 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x08, 0x66, 0x69, + 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x22, 0xc6, 0x01, 0x0a, 0x0a, 0x53, 0x63, 0x61, 0x6e, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x3a, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x22, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, + 0x53, 0x63, 0x61, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x53, 0x63, 0x61, 0x6e, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x66, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x5f, 0x72, 0x65, 0x61, + 0x73, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x66, 0x61, 0x69, 0x6c, 0x75, + 0x72, 0x65, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0x55, 0x0a, 0x0e, 0x53, 0x63, 0x61, 0x6e, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x0f, 0x0a, 0x0b, 0x55, 0x4e, + 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x53, + 0x55, 0x43, 0x43, 0x45, 0x45, 0x44, 0x45, 0x44, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x50, 0x41, + 0x52, 0x54, 0x49, 0x41, 0x4c, 0x4c, 0x59, 0x5f, 0x53, 0x55, 0x43, 0x43, 0x45, 0x45, 0x44, 0x45, + 0x44, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x03, 0x22, + 0x69, 0x0a, 0x0c, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, + 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2b, 0x0a, + 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, + 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x53, 0x63, 0x61, 0x6e, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x89, 0x14, 0x0a, 0x07, 0x50, + 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0b, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, + 0x6f, 0x64, 0x65, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x73, 0x63, 0x61, 0x6c, + 0x69, 0x62, 0x72, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x43, 0x6f, 0x64, 0x65, 0x12, 0x21, 0x0a, 0x04, 0x70, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x50, 0x75, 0x72, + 0x6c, 0x52, 0x04, 0x70, 0x75, 0x72, 0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x65, 0x63, 0x6f, 0x73, 0x79, + 0x73, 0x74, 0x65, 0x6d, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x63, 0x6f, 0x73, + 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x1c, 0x0a, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x65, 0x78, 0x74, 0x72, 0x61, 0x63, 0x74, 0x6f, 0x72, + 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x78, 0x74, 0x72, 0x61, 0x63, 0x74, 0x6f, + 0x72, 0x12, 0x49, 0x0a, 0x0f, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x5f, 0x6d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x73, 0x63, 0x61, + 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x50, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x50, 0x61, 0x63, 0x6b, 0x61, + 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x0e, 0x70, 0x79, + 0x74, 0x68, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x59, 0x0a, 0x13, + 0x6a, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x73, 0x63, 0x61, 0x6c, + 0x69, 0x62, 0x72, 0x2e, 0x4a, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x50, 0x61, + 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4a, 0x53, 0x4f, 0x4e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, + 0x61, 0x48, 0x00, 0x52, 0x12, 0x6a, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x40, 0x0a, 0x0c, 0x61, 0x70, 0x6b, 0x5f, 0x6d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, + 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x41, 0x50, 0x4b, 0x50, 0x61, 0x63, 0x6b, 0x61, + 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x0b, 0x61, 0x70, + 0x6b, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x43, 0x0a, 0x0d, 0x64, 0x70, 0x6b, + 0x67, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1c, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x44, 0x50, 0x4b, 0x47, 0x50, + 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x00, + 0x52, 0x0c, 0x64, 0x70, 0x6b, 0x67, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x40, + 0x0a, 0x0c, 0x72, 0x70, 0x6d, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x09, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x52, + 0x50, 0x4d, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, + 0x61, 0x48, 0x00, 0x52, 0x0b, 0x72, 0x70, 0x6d, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x12, 0x40, 0x0a, 0x0c, 0x63, 0x6f, 0x73, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, + 0x2e, 0x43, 0x4f, 0x53, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x0b, 0x63, 0x6f, 0x73, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x12, 0x48, 0x0a, 0x11, 0x64, 0x65, 0x70, 0x73, 0x6a, 0x73, 0x6f, 0x6e, 0x5f, 0x6d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x28, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, + 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x44, 0x45, 0x50, 0x53, 0x4a, 0x53, 0x4f, 0x4e, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x10, 0x64, 0x65, 0x70, 0x73, + 0x6a, 0x73, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x43, 0x0a, 0x0d, + 0x73, 0x70, 0x64, 0x78, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x0e, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x53, 0x50, + 0x44, 0x58, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, + 0x61, 0x48, 0x00, 0x52, 0x0c, 0x73, 0x70, 0x64, 0x78, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, + 0x61, 0x12, 0x52, 0x0a, 0x15, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, + 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1c, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x4a, 0x61, 0x76, 0x61, 0x41, + 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x00, + 0x52, 0x13, 0x6a, 0x61, 0x76, 0x61, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x55, 0x0a, 0x16, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x6c, 0x6f, + 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, + 0x1f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, + 0x4a, 0x61, 0x76, 0x61, 0x4c, 0x6f, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x14, 0x6a, 0x61, 0x76, 0x61, 0x4c, 0x6f, 0x63, 0x6b, + 0x66, 0x69, 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x49, 0x0a, 0x0f, + 0x70, 0x61, 0x63, 0x6d, 0x61, 0x6e, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, + 0x24, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, + 0x50, 0x41, 0x43, 0x4d, 0x41, 0x4e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x0e, 0x70, 0x61, 0x63, 0x6d, 0x61, 0x6e, 0x4d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x40, 0x0a, 0x0c, 0x6e, 0x69, 0x78, 0x5f, 0x6d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x25, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, + 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x4e, 0x69, 0x78, 0x50, 0x61, 0x63, 0x6b, 0x61, + 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x0b, 0x6e, 0x69, + 0x78, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x55, 0x0a, 0x16, 0x6b, 0x65, 0x72, + 0x6e, 0x65, 0x6c, 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0x18, 0x26, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x73, 0x63, 0x61, 0x6c, + 0x69, 0x62, 0x72, 0x2e, 0x4b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x14, 0x6b, 0x65, 0x72, 0x6e, + 0x65, 0x6c, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x12, 0x45, 0x0a, 0x10, 0x76, 0x6d, 0x6c, 0x69, 0x6e, 0x75, 0x7a, 0x5f, 0x6d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x18, 0x27, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x73, 0x63, 0x61, + 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x56, 0x6d, 0x6c, 0x69, 0x6e, 0x75, 0x7a, 0x4d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x0f, 0x76, 0x6d, 0x6c, 0x69, 0x6e, 0x75, 0x7a, 0x4d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x4c, 0x0a, 0x10, 0x70, 0x6f, 0x72, 0x74, 0x61, + 0x67, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x29, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1f, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x50, 0x6f, 0x72, 0x74, + 0x61, 0x67, 0x65, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x48, 0x00, 0x52, 0x0f, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x67, 0x65, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x40, 0x0a, 0x0c, 0x6f, 0x73, 0x76, 0x5f, 0x6d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x73, 0x63, + 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x4f, 0x53, 0x56, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x0b, 0x6f, 0x73, 0x76, 0x4d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x67, 0x0a, 0x1c, 0x70, 0x79, 0x74, 0x68, 0x6f, + 0x6e, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x5f, 0x6d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x15, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, + 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x50, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x52, 0x65, + 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x48, 0x00, 0x52, 0x1a, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, + 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x12, 0x52, 0x0a, 0x15, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x5f, 0x73, 0x65, 0x74, 0x75, 0x70, + 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x2c, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1c, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x50, 0x79, 0x74, 0x68, 0x6f, 0x6e, + 0x53, 0x65, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, + 0x13, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x12, 0x6a, 0x0a, 0x1d, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, + 0x72, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x6d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x16, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x73, 0x63, + 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, + 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, + 0x61, 0x48, 0x00, 0x52, 0x1b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x43, + 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x12, 0x43, 0x0a, 0x0d, 0x73, 0x6e, 0x61, 0x70, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, + 0x61, 0x18, 0x17, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, + 0x72, 0x2e, 0x53, 0x4e, 0x41, 0x50, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x0c, 0x73, 0x6e, 0x61, 0x70, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x4c, 0x0a, 0x10, 0x66, 0x6c, 0x61, 0x74, 0x70, 0x61, 0x6b, + 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x18, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1f, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x46, 0x6c, 0x61, 0x74, 0x70, 0x61, + 0x6b, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x48, 0x00, 0x52, 0x0f, 0x66, 0x6c, 0x61, 0x74, 0x70, 0x61, 0x6b, 0x4d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0x12, 0x46, 0x0a, 0x11, 0x6d, 0x61, 0x63, 0x5f, 0x61, 0x70, 0x70, 0x73, 0x5f, + 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x22, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, + 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x4d, 0x61, 0x63, 0x41, 0x70, 0x70, 0x73, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x0f, 0x6d, 0x61, 0x63, 0x41, + 0x70, 0x70, 0x73, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x80, 0x01, 0x0a, 0x25, + 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x5f, 0x72, 0x75, 0x6e, 0x74, 0x69, + 0x6d, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x6d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x19, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x73, 0x63, + 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, + 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x22, 0x63, 0x6f, 0x6e, 0x74, + 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x43, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x40, + 0x0a, 0x0c, 0x63, 0x64, 0x78, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x1e, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x43, + 0x44, 0x58, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, + 0x61, 0x48, 0x00, 0x52, 0x0b, 0x63, 0x64, 0x78, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x12, 0x5a, 0x0a, 0x1b, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x5f, 0x6f, 0x73, 0x5f, 0x76, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, + 0x21, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, + 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x4f, 0x53, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x48, 0x00, 0x52, 0x18, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x4f, 0x73, 0x56, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x4f, 0x0a, 0x11, + 0x68, 0x6f, 0x6d, 0x65, 0x62, 0x72, 0x65, 0x77, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, + 0x61, 0x18, 0x2a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, + 0x72, 0x2e, 0x48, 0x6f, 0x6d, 0x65, 0x62, 0x72, 0x65, 0x77, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, + 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x10, 0x68, 0x6f, 0x6d, + 0x65, 0x62, 0x72, 0x65, 0x77, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x41, 0x0a, + 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x1c, 0x20, 0x03, + 0x28, 0x0e, 0x32, 0x1f, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x50, 0x61, 0x63, + 0x6b, 0x61, 0x67, 0x65, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, + 0x6e, 0x75, 0x6d, 0x52, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x12, 0x3a, 0x0a, 0x0d, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, + 0x73, 0x18, 0x23, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, + 0x72, 0x2e, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x0c, + 0x6c, 0x61, 0x79, 0x65, 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x22, 0x60, 0x0a, 0x0e, + 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x0f, + 0x0a, 0x0b, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, + 0x10, 0x0a, 0x0c, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x41, 0x4c, 0x10, + 0x01, 0x12, 0x15, 0x0a, 0x11, 0x49, 0x4e, 0x53, 0x49, 0x44, 0x45, 0x5f, 0x4f, 0x53, 0x5f, 0x50, + 0x41, 0x43, 0x4b, 0x41, 0x47, 0x45, 0x10, 0x02, 0x12, 0x14, 0x0a, 0x10, 0x49, 0x4e, 0x53, 0x49, + 0x44, 0x45, 0x5f, 0x43, 0x41, 0x43, 0x48, 0x45, 0x5f, 0x44, 0x49, 0x52, 0x10, 0x03, 0x42, 0x0a, + 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, + 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x22, 0x42, 0x0a, 0x14, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x43, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x12, + 0x0a, 0x04, 0x72, 0x65, 0x70, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x65, + 0x70, 0x6f, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x22, 0x7b, 0x0a, 0x0c, 0x4c, 0x61, + 0x79, 0x65, 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, + 0x64, 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, + 0x12, 0x17, 0x0a, 0x07, 0x64, 0x69, 0x66, 0x66, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x06, 0x64, 0x69, 0x66, 0x66, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, + 0x6d, 0x61, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, + 0x61, 0x6e, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x69, 0x6e, 0x5f, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x69, + 0x6d, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x6e, 0x42, 0x61, + 0x73, 0x65, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x22, 0xc8, 0x01, 0x0a, 0x04, 0x50, 0x75, 0x72, 0x6c, + 0x12, 0x12, 0x0a, 0x04, 0x70, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x70, 0x75, 0x72, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, + 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, + 0x61, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, + 0x70, 0x61, 0x63, 0x65, 0x12, 0x32, 0x0a, 0x0a, 0x71, 0x75, 0x61, 0x6c, 0x69, 0x66, 0x69, 0x65, + 0x72, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, + 0x62, 0x72, 0x2e, 0x51, 0x75, 0x61, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x0a, 0x71, 0x75, + 0x61, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x72, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x62, 0x70, + 0x61, 0x74, 0x68, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x75, 0x62, 0x70, 0x61, + 0x74, 0x68, 0x22, 0x33, 0x0a, 0x09, 0x51, 0x75, 0x61, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, + 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, + 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x92, 0x01, 0x0a, 0x07, 0x46, 0x69, 0x6e, 0x64, + 0x69, 0x6e, 0x67, 0x12, 0x23, 0x0a, 0x03, 0x61, 0x64, 0x76, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x11, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x41, 0x64, 0x76, 0x69, 0x73, + 0x6f, 0x72, 0x79, 0x52, 0x03, 0x61, 0x64, 0x76, 0x12, 0x2e, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, + 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, + 0x62, 0x72, 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, + 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x78, 0x74, 0x72, + 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x78, 0x74, 0x72, 0x61, 0x12, 0x1c, + 0x0a, 0x09, 0x64, 0x65, 0x74, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x09, 0x64, 0x65, 0x74, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x22, 0xa1, 0x02, 0x0a, + 0x08, 0x41, 0x64, 0x76, 0x69, 0x73, 0x6f, 0x72, 0x79, 0x12, 0x23, 0x0a, 0x02, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, + 0x41, 0x64, 0x76, 0x69, 0x73, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x52, 0x02, 0x69, 0x64, 0x12, 0x2e, + 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1a, 0x2e, 0x73, + 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x41, 0x64, 0x76, 0x69, 0x73, 0x6f, 0x72, 0x79, 0x2e, + 0x54, 0x79, 0x70, 0x65, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x14, + 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, + 0x69, 0x74, 0x6c, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x26, 0x0a, 0x0e, 0x72, 0x65, 0x63, 0x6f, 0x6d, 0x6d, + 0x65, 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, + 0x72, 0x65, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23, + 0x0a, 0x03, 0x73, 0x65, 0x76, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x73, 0x63, + 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x53, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x52, 0x03, + 0x73, 0x65, 0x76, 0x22, 0x3b, 0x0a, 0x08, 0x54, 0x79, 0x70, 0x65, 0x45, 0x6e, 0x75, 0x6d, 0x12, + 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, + 0x56, 0x55, 0x4c, 0x4e, 0x45, 0x52, 0x41, 0x42, 0x49, 0x4c, 0x49, 0x54, 0x59, 0x10, 0x01, 0x12, + 0x0f, 0x0a, 0x0b, 0x43, 0x49, 0x53, 0x5f, 0x46, 0x49, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x02, + 0x22, 0x48, 0x0a, 0x0a, 0x41, 0x64, 0x76, 0x69, 0x73, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x12, 0x1c, + 0x0a, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, + 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x22, 0xf1, 0x01, 0x0a, 0x08, 0x53, + 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x12, 0x3a, 0x0a, 0x08, 0x73, 0x65, 0x76, 0x65, 0x72, + 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1e, 0x2e, 0x73, 0x63, 0x61, 0x6c, + 0x69, 0x62, 0x72, 0x2e, 0x53, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x2e, 0x53, 0x65, 0x76, + 0x65, 0x72, 0x69, 0x74, 0x79, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x08, 0x73, 0x65, 0x76, 0x65, 0x72, + 0x69, 0x74, 0x79, 0x12, 0x26, 0x0a, 0x07, 0x63, 0x76, 0x73, 0x73, 0x5f, 0x76, 0x32, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x43, + 0x56, 0x53, 0x53, 0x52, 0x06, 0x63, 0x76, 0x73, 0x73, 0x56, 0x32, 0x12, 0x26, 0x0a, 0x07, 0x63, + 0x76, 0x73, 0x73, 0x5f, 0x76, 0x33, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x73, + 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x43, 0x56, 0x53, 0x53, 0x52, 0x06, 0x63, 0x76, 0x73, + 0x73, 0x56, 0x33, 0x22, 0x59, 0x0a, 0x0c, 0x53, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x45, + 0x6e, 0x75, 0x6d, 0x12, 0x0f, 0x0a, 0x0b, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, + 0x45, 0x44, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x4d, 0x49, 0x4e, 0x49, 0x4d, 0x41, 0x4c, 0x10, + 0x01, 0x12, 0x07, 0x0a, 0x03, 0x4c, 0x4f, 0x57, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x4d, 0x45, + 0x44, 0x49, 0x55, 0x4d, 0x10, 0x03, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x49, 0x47, 0x48, 0x10, 0x04, + 0x12, 0x0c, 0x0a, 0x08, 0x43, 0x52, 0x49, 0x54, 0x49, 0x43, 0x41, 0x4c, 0x10, 0x05, 0x22, 0x7d, + 0x0a, 0x04, 0x43, 0x56, 0x53, 0x53, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x73, + 0x63, 0x6f, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x02, 0x52, 0x09, 0x62, 0x61, 0x73, 0x65, + 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, + 0x6c, 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x02, 0x52, 0x0d, 0x74, + 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x6c, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x2f, 0x0a, 0x13, + 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x5f, 0x73, 0x63, + 0x6f, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x02, 0x52, 0x12, 0x65, 0x6e, 0x76, 0x69, 0x72, + 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x22, 0x57, 0x0a, + 0x0d, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x2a, + 0x0a, 0x07, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x10, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, + 0x65, 0x52, 0x07, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x6f, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x6f, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x52, 0x0a, 0x15, 0x50, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, - 0x21, 0x0a, 0x0c, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4e, 0x61, - 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x4e, - 0x61, 0x6d, 0x65, 0x12, 0x13, 0x0a, 0x05, 0x6f, 0x73, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x6f, 0x73, 0x49, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x6f, 0x73, 0x5f, 0x76, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0b, 0x6f, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1e, 0x0a, 0x0a, - 0x6d, 0x61, 0x69, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0a, 0x6d, 0x61, 0x69, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x22, 0x0a, 0x0c, - 0x61, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0c, 0x61, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, - 0x12, 0x18, 0x0a, 0x07, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x07, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x22, 0xee, 0x02, 0x0a, 0x13, 0x44, - 0x50, 0x4b, 0x47, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, - 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x0a, - 0x0f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x56, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x13, 0x0a, 0x05, 0x6f, 0x73, 0x5f, 0x69, 0x64, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6f, 0x73, 0x49, 0x64, 0x12, 0x2e, 0x0a, 0x13, 0x6f, - 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x6f, 0x73, 0x56, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x64, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x6f, - 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0b, 0x6f, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, - 0x1e, 0x0a, 0x0a, 0x6d, 0x61, 0x69, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, 0x08, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x61, 0x69, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, - 0x22, 0x0a, 0x0c, 0x61, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x18, - 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, - 0x75, 0x72, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x0a, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0xb4, 0x02, 0x0a, 0x12, - 0x52, 0x50, 0x4d, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, - 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, - 0x72, 0x70, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x52, 0x70, 0x6d, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x05, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x13, 0x0a, 0x05, 0x6f, 0x73, - 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6f, 0x73, 0x49, 0x64, 0x12, - 0x22, 0x0a, 0x0d, 0x6f, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6f, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 0x49, 0x64, 0x12, 0x1e, 0x0a, 0x0b, 0x6f, 0x73, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, - 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, 0x73, 0x42, 0x75, 0x69, 0x6c, - 0x64, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x6f, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x07, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, - 0x76, 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x76, 0x65, - 0x6e, 0x64, 0x6f, 0x72, 0x12, 0x22, 0x0a, 0x0c, 0x61, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, - 0x74, 0x75, 0x72, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x72, 0x63, 0x68, - 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6c, 0x69, 0x63, 0x65, - 0x6e, 0x73, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6c, 0x69, 0x63, 0x65, 0x6e, - 0x73, 0x65, 0x22, 0xa1, 0x01, 0x0a, 0x12, 0x43, 0x4f, 0x53, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, - 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, - 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, - 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x61, 0x74, 0x65, 0x67, - 0x6f, 0x72, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x61, 0x74, 0x65, 0x67, - 0x6f, 0x72, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0d, 0x6f, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6f, 0x73, 0x56, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x80, 0x02, 0x0a, 0x15, 0x50, 0x41, 0x43, 0x4d, 0x41, - 0x4e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4e, - 0x61, 0x6d, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x76, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x70, 0x61, - 0x63, 0x6b, 0x61, 0x67, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x13, 0x0a, 0x05, - 0x6f, 0x73, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6f, 0x73, 0x49, - 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x6f, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, - 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6f, 0x73, 0x56, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x2f, 0x0a, 0x13, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, - 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x12, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x31, 0x0a, 0x14, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, - 0x65, 0x5f, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x44, 0x65, 0x70, - 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x22, 0x93, 0x02, 0x0a, 0x12, 0x4e, 0x69, - 0x78, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x16, 0x0a, 0x06, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x75, 0x74, 0x68, 0x6f, + 0x72, 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, + 0x75, 0x74, 0x68, 0x6f, 0x72, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x22, 0x7d, 0x0a, 0x1d, 0x4a, 0x61, + 0x76, 0x61, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4a, + 0x53, 0x4f, 0x4e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x16, 0x0a, 0x06, 0x61, + 0x75, 0x74, 0x68, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x75, 0x74, + 0x68, 0x6f, 0x72, 0x12, 0x20, 0x0a, 0x0b, 0x6d, 0x61, 0x69, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, + 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x6d, 0x61, 0x69, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x6f, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x73, 0x22, 0xef, 0x01, 0x0a, 0x12, 0x41, 0x50, + 0x4b, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4e, - 0x61, 0x6d, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x76, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x70, 0x61, - 0x63, 0x6b, 0x61, 0x67, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, - 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0b, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x48, 0x61, 0x73, 0x68, 0x12, - 0x25, 0x0a, 0x0e, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6f, 0x75, 0x74, 0x70, 0x75, - 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, - 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x12, 0x13, 0x0a, 0x05, 0x6f, 0x73, 0x5f, 0x69, 0x64, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6f, 0x73, 0x49, 0x64, 0x12, 0x2e, 0x0a, 0x13, 0x6f, - 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x6f, 0x73, 0x56, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x64, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x6f, - 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0b, 0x6f, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, - 0x72, 0x0a, 0x10, 0x44, 0x45, 0x50, 0x53, 0x4a, 0x53, 0x4f, 0x4e, 0x4d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x61, 0x63, 0x6b, 0x61, - 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, - 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0e, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, - 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, - 0x79, 0x70, 0x65, 0x22, 0xfc, 0x01, 0x0a, 0x13, 0x53, 0x4e, 0x41, 0x50, 0x50, 0x61, 0x63, 0x6b, - 0x61, 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, - 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x67, 0x72, 0x61, - 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x67, 0x72, 0x61, 0x64, 0x65, 0x12, - 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, - 0x79, 0x70, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x61, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, - 0x75, 0x72, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x61, 0x72, 0x63, 0x68, - 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x13, 0x0a, 0x05, 0x6f, 0x73, 0x5f, - 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6f, 0x73, 0x49, 0x64, 0x12, 0x2e, - 0x0a, 0x13, 0x6f, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x64, - 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x6f, 0x73, 0x56, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x64, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x22, - 0x0a, 0x0d, 0x6f, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, - 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6f, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x49, 0x64, 0x22, 0x9d, 0x01, 0x0a, 0x16, 0x50, 0x6f, 0x72, 0x74, 0x61, 0x67, 0x65, 0x50, 0x61, - 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x21, 0x0a, - 0x0c, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, - 0x12, 0x27, 0x0a, 0x0f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x70, 0x61, 0x63, 0x6b, 0x61, - 0x67, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x13, 0x0a, 0x05, 0x6f, 0x73, 0x5f, - 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6f, 0x73, 0x49, 0x64, 0x12, 0x22, - 0x0a, 0x0d, 0x6f, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6f, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x49, 0x64, 0x22, 0xb6, 0x02, 0x0a, 0x16, 0x46, 0x6c, 0x61, 0x74, 0x70, 0x61, 0x6b, 0x50, 0x61, - 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x21, 0x0a, - 0x0c, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, - 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x49, 0x64, 0x12, - 0x27, 0x0a, 0x0f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, - 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x65, 0x6c, 0x65, - 0x61, 0x73, 0x65, 0x5f, 0x64, 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, - 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x44, 0x61, 0x74, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x6f, - 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x73, - 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x13, 0x0a, 0x05, 0x6f, 0x73, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, + 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x5f, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, + 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x13, 0x0a, 0x05, 0x6f, 0x73, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6f, 0x73, 0x49, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x6f, 0x73, 0x5f, - 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, + 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6f, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1e, 0x0a, - 0x0b, 0x6f, 0x73, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x09, 0x6f, 0x73, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x64, 0x12, 0x1c, 0x0a, - 0x09, 0x64, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x09, 0x64, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x72, 0x22, 0xe8, 0x02, 0x0a, 0x14, - 0x4b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61, + 0x0a, 0x6d, 0x61, 0x69, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0a, 0x6d, 0x61, 0x69, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x22, 0x0a, + 0x0c, 0x61, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, + 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x18, 0x07, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x22, 0xee, 0x02, 0x0a, 0x13, + 0x44, 0x50, 0x4b, 0x47, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x61, 0x63, 0x6b, 0x61, + 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0d, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x27, + 0x0a, 0x0f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, + 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x13, 0x0a, 0x05, 0x6f, 0x73, 0x5f, 0x69, 0x64, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6f, 0x73, 0x49, 0x64, 0x12, 0x2e, 0x0a, 0x13, + 0x6f, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x6f, 0x73, 0x56, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x64, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0d, + 0x6f, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6f, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, + 0x12, 0x1e, 0x0a, 0x0a, 0x6d, 0x61, 0x69, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, 0x08, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x61, 0x69, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, + 0x12, 0x22, 0x0a, 0x0c, 0x61, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, + 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, + 0x74, 0x75, 0x72, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x0a, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0xb4, 0x02, 0x0a, + 0x12, 0x52, 0x50, 0x4d, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x61, 0x63, 0x6b, 0x61, + 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x5f, 0x72, 0x70, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x52, 0x70, 0x6d, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x13, 0x0a, 0x05, 0x6f, + 0x73, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6f, 0x73, 0x49, 0x64, + 0x12, 0x22, 0x0a, 0x0d, 0x6f, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, + 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6f, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, + 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1e, 0x0a, 0x0b, 0x6f, 0x73, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, + 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, 0x73, 0x42, 0x75, 0x69, + 0x6c, 0x64, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x6f, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, + 0x06, 0x76, 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x76, + 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x12, 0x22, 0x0a, 0x0c, 0x61, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, + 0x63, 0x74, 0x75, 0x72, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x72, 0x63, + 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6c, 0x69, 0x63, + 0x65, 0x6e, 0x73, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6c, 0x69, 0x63, 0x65, + 0x6e, 0x73, 0x65, 0x22, 0xa1, 0x01, 0x0a, 0x12, 0x43, 0x4f, 0x53, 0x50, 0x61, 0x63, 0x6b, 0x61, + 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, + 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x61, 0x74, 0x65, + 0x67, 0x6f, 0x72, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x61, 0x74, 0x65, + 0x67, 0x6f, 0x72, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, + 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, 0x73, 0x56, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0d, 0x6f, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6f, 0x73, 0x56, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x80, 0x02, 0x0a, 0x15, 0x50, 0x41, 0x43, 0x4d, + 0x41, 0x4e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, + 0x61, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, + 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, + 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x70, + 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x13, 0x0a, + 0x05, 0x6f, 0x73, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6f, 0x73, + 0x49, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x6f, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6f, 0x73, 0x56, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x2f, 0x0a, 0x13, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, + 0x65, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x12, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x44, 0x65, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x31, 0x0a, 0x14, 0x70, 0x61, 0x63, 0x6b, 0x61, + 0x67, 0x65, 0x5f, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x44, 0x65, + 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x22, 0x93, 0x02, 0x0a, 0x12, 0x4e, + 0x69, 0x78, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, + 0x61, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, + 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, + 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x70, + 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x0a, + 0x0c, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x48, 0x61, 0x73, 0x68, + 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6f, 0x75, 0x74, 0x70, + 0x75, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, + 0x65, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x12, 0x13, 0x0a, 0x05, 0x6f, 0x73, 0x5f, 0x69, 0x64, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6f, 0x73, 0x49, 0x64, 0x12, 0x2e, 0x0a, 0x13, + 0x6f, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x6f, 0x73, 0x56, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x64, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0d, + 0x6f, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6f, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, + 0x22, 0x72, 0x0a, 0x10, 0x44, 0x45, 0x50, 0x53, 0x4a, 0x53, 0x4f, 0x4e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x12, 0x29, 0x0a, 0x10, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x6d, - 0x61, 0x67, 0x69, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x70, 0x61, 0x63, 0x6b, - 0x61, 0x67, 0x65, 0x56, 0x65, 0x72, 0x6d, 0x61, 0x67, 0x69, 0x63, 0x12, 0x49, 0x0a, 0x21, 0x70, - 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x76, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1e, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x53, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x65, 0x6e, - 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x13, 0x0a, 0x05, 0x6f, 0x73, 0x5f, 0x69, 0x64, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6f, 0x73, 0x49, 0x64, 0x12, 0x2e, 0x0a, 0x13, 0x6f, - 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x6f, 0x73, 0x56, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x64, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x6f, - 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0b, 0x6f, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, - 0x25, 0x0a, 0x0e, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x6f, - 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, - 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x22, 0x8e, 0x03, 0x0a, 0x0f, 0x56, 0x6d, 0x6c, 0x69, 0x6e, - 0x75, 0x7a, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, - 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x61, 0x72, 0x63, 0x68, - 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, - 0x61, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x12, 0x29, 0x0a, 0x10, - 0x65, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, - 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, - 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, - 0x1f, 0x0a, 0x0b, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x73, 0x77, 0x61, 0x70, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x18, - 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x72, 0x6f, 0x6f, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, - 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x4d, 0x6f, 0x64, 0x65, - 0x12, 0x13, 0x0a, 0x05, 0x6f, 0x73, 0x5f, 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x6f, 0x73, 0x49, 0x64, 0x12, 0x2e, 0x0a, 0x13, 0x6f, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x11, 0x6f, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x64, - 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x6f, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6f, 0x73, - 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x0a, 0x72, 0x77, 0x5f, - 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x66, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, - 0x77, 0x52, 0x6f, 0x6f, 0x74, 0x46, 0x73, 0x22, 0xbb, 0x03, 0x0a, 0x0f, 0x4d, 0x61, 0x63, 0x41, - 0x70, 0x70, 0x73, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x2e, 0x0a, 0x13, 0x62, - 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x5f, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, - 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2b, 0x0a, 0x11, 0x62, - 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x49, 0x64, - 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x3d, 0x0a, 0x1b, 0x62, 0x75, 0x6e, 0x64, - 0x6c, 0x65, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x18, 0x62, - 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x53, 0x68, 0x6f, 0x72, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x2b, 0x0a, 0x11, 0x62, 0x75, 0x6e, 0x64, 0x6c, - 0x65, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x10, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, - 0x61, 0x62, 0x6c, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x5f, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x62, 0x75, 0x6e, 0x64, 0x6c, - 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2e, 0x0a, 0x13, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x5f, - 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x11, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, - 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x5f, - 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0f, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x12, 0x25, 0x0a, 0x0e, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, - 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x64, 0x75, - 0x63, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x72, 0x6f, - 0x64, 0x75, 0x63, 0x74, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x55, 0x72, 0x6c, 0x22, 0x4c, 0x0a, 0x13, 0x53, 0x50, 0x44, 0x58, 0x50, 0x61, 0x63, - 0x6b, 0x61, 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x21, 0x0a, 0x04, - 0x70, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x73, 0x63, 0x61, - 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x50, 0x75, 0x72, 0x6c, 0x52, 0x04, 0x70, 0x75, 0x72, 0x6c, 0x12, - 0x12, 0x0a, 0x04, 0x63, 0x70, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x63, - 0x70, 0x65, 0x73, 0x22, 0x4b, 0x0a, 0x12, 0x43, 0x44, 0x58, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, - 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x21, 0x0a, 0x04, 0x70, 0x75, 0x72, - 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, - 0x72, 0x2e, 0x50, 0x75, 0x72, 0x6c, 0x52, 0x04, 0x70, 0x75, 0x72, 0x6c, 0x12, 0x12, 0x0a, 0x04, - 0x63, 0x70, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x63, 0x70, 0x65, 0x73, - 0x22, 0x65, 0x0a, 0x13, 0x4a, 0x61, 0x76, 0x61, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x4d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x72, 0x74, 0x69, 0x66, - 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x72, - 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x67, 0x72, 0x6f, 0x75, - 0x70, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x67, 0x72, 0x6f, 0x75, - 0x70, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x68, 0x61, 0x31, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x73, 0x68, 0x61, 0x31, 0x22, 0x78, 0x0a, 0x14, 0x4a, 0x61, 0x76, 0x61, 0x4c, - 0x6f, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, - 0x1f, 0x0a, 0x0b, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x49, 0x64, - 0x12, 0x19, 0x0a, 0x08, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x07, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x64, - 0x65, 0x70, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x76, 0x61, 0x6c, 0x73, 0x18, 0x03, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x0c, 0x64, 0x65, 0x70, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x56, 0x61, 0x6c, - 0x73, 0x22, 0x86, 0x01, 0x0a, 0x12, 0x4f, 0x53, 0x56, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, - 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x75, 0x72, 0x6c, - 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x75, 0x72, - 0x6c, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x12, 0x1c, 0x0a, - 0x09, 0x65, 0x63, 0x6f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x09, 0x65, 0x63, 0x6f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x1d, 0x0a, 0x0a, 0x63, - 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x65, 0x5f, 0x61, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x65, 0x41, 0x73, 0x22, 0x86, 0x01, 0x0a, 0x1a, 0x50, - 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, - 0x73, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x39, 0x0a, 0x19, 0x68, 0x61, 0x73, - 0x68, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x5f, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x16, 0x68, 0x61, - 0x73, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x4d, 0x6f, 0x64, 0x65, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x73, 0x12, 0x2d, 0x0a, 0x12, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, - 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x11, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x61, - 0x74, 0x6f, 0x72, 0x22, 0x44, 0x0a, 0x13, 0x50, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x53, 0x65, 0x74, - 0x75, 0x70, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x2d, 0x0a, 0x12, 0x76, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x61, 0x74, 0x6f, 0x72, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x43, - 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x22, 0xf7, 0x02, 0x0a, 0x1b, 0x43, 0x6f, - 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, - 0x72, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x25, 0x0a, 0x0e, 0x6e, 0x61, 0x6d, - 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0d, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, - 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, - 0x21, 0x0a, 0x0c, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x44, 0x69, 0x67, 0x65, - 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, - 0x70, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x70, 0x69, 0x64, 0x12, 0x20, - 0x0a, 0x0b, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x74, 0x65, 0x72, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x74, 0x65, 0x72, - 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5f, 0x6b, 0x65, 0x79, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, - 0x4b, 0x65, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x5f, 0x64, 0x69, 0x72, - 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x44, 0x69, 0x72, - 0x12, 0x1b, 0x0a, 0x09, 0x75, 0x70, 0x70, 0x65, 0x72, 0x5f, 0x64, 0x69, 0x72, 0x18, 0x09, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x70, 0x70, 0x65, 0x72, 0x44, 0x69, 0x72, 0x12, 0x19, 0x0a, - 0x08, 0x77, 0x6f, 0x72, 0x6b, 0x5f, 0x64, 0x69, 0x72, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x77, 0x6f, 0x72, 0x6b, 0x44, 0x69, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x0b, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x70, 0x6f, 0x64, 0x5f, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x6f, 0x64, 0x4e, - 0x61, 0x6d, 0x65, 0x22, 0xea, 0x01, 0x0a, 0x22, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, - 0x72, 0x64, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x74, 0x79, 0x70, 0x65, 0x22, 0xfc, 0x01, 0x0a, 0x13, 0x53, 0x4e, 0x41, 0x50, 0x50, 0x61, 0x63, + 0x6b, 0x61, 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x67, 0x72, + 0x61, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x67, 0x72, 0x61, 0x64, 0x65, + 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x74, 0x79, 0x70, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x61, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, + 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x61, 0x72, 0x63, + 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x13, 0x0a, 0x05, 0x6f, 0x73, + 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6f, 0x73, 0x49, 0x64, 0x12, + 0x2e, 0x0a, 0x13, 0x6f, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, + 0x64, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x6f, 0x73, + 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x64, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, + 0x22, 0x0a, 0x0d, 0x6f, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, + 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6f, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x49, 0x64, 0x22, 0x9d, 0x01, 0x0a, 0x16, 0x50, 0x6f, 0x72, 0x74, 0x61, 0x67, 0x65, 0x50, + 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x21, + 0x0a, 0x0c, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, + 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x76, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x70, 0x61, 0x63, 0x6b, + 0x61, 0x67, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x13, 0x0a, 0x05, 0x6f, 0x73, + 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6f, 0x73, 0x49, 0x64, 0x12, + 0x22, 0x0a, 0x0d, 0x6f, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6f, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x49, 0x64, 0x22, 0xb6, 0x02, 0x0a, 0x16, 0x46, 0x6c, 0x61, 0x74, 0x70, 0x61, 0x6b, 0x50, + 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x21, + 0x0a, 0x0c, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, + 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x49, 0x64, + 0x12, 0x27, 0x0a, 0x0f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x70, 0x61, 0x63, 0x6b, 0x61, + 0x67, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x65, 0x6c, + 0x65, 0x61, 0x73, 0x65, 0x5f, 0x64, 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0b, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x44, 0x61, 0x74, 0x65, 0x12, 0x17, 0x0a, 0x07, + 0x6f, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, + 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x13, 0x0a, 0x05, 0x6f, 0x73, 0x5f, 0x69, 0x64, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6f, 0x73, 0x49, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x6f, 0x73, + 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0b, 0x6f, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1e, + 0x0a, 0x0b, 0x6f, 0x73, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, 0x73, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x64, 0x12, 0x1c, + 0x0a, 0x09, 0x64, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x64, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x72, 0x22, 0xe8, 0x02, 0x0a, + 0x14, 0x4b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, + 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x61, 0x63, + 0x6b, 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x70, 0x61, 0x63, 0x6b, + 0x61, 0x67, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0e, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x12, 0x29, 0x0a, 0x10, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x76, 0x65, 0x72, + 0x6d, 0x61, 0x67, 0x69, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x70, 0x61, 0x63, + 0x6b, 0x61, 0x67, 0x65, 0x56, 0x65, 0x72, 0x6d, 0x61, 0x67, 0x69, 0x63, 0x12, 0x49, 0x0a, 0x21, + 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x76, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, + 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1e, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, + 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x65, + 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x13, 0x0a, 0x05, 0x6f, 0x73, 0x5f, 0x69, 0x64, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6f, 0x73, 0x49, 0x64, 0x12, 0x2e, 0x0a, 0x13, + 0x6f, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x6f, 0x73, 0x56, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x64, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0d, + 0x6f, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6f, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, + 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x61, 0x75, 0x74, 0x68, + 0x6f, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, + 0x65, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x22, 0x8e, 0x03, 0x0a, 0x0f, 0x56, 0x6d, 0x6c, 0x69, + 0x6e, 0x75, 0x7a, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, + 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x61, 0x72, 0x63, + 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0c, 0x61, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x12, 0x29, 0x0a, + 0x10, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, + 0x64, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x6f, 0x72, 0x6d, + 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, + 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x73, 0x77, 0x61, 0x70, 0x44, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x72, 0x6f, 0x6f, 0x74, 0x44, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x5f, 0x6d, 0x6f, 0x64, 0x65, + 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x4d, 0x6f, 0x64, + 0x65, 0x12, 0x13, 0x0a, 0x05, 0x6f, 0x73, 0x5f, 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x6f, 0x73, 0x49, 0x64, 0x12, 0x2e, 0x0a, 0x13, 0x6f, 0x73, 0x5f, 0x76, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0a, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x11, 0x6f, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, + 0x64, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x6f, 0x73, 0x5f, 0x76, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6f, + 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x0a, 0x72, 0x77, + 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x66, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, + 0x72, 0x77, 0x52, 0x6f, 0x6f, 0x74, 0x46, 0x73, 0x22, 0xbb, 0x03, 0x0a, 0x0f, 0x4d, 0x61, 0x63, + 0x41, 0x70, 0x70, 0x73, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x2e, 0x0a, 0x13, + 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x5f, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x62, 0x75, 0x6e, 0x64, 0x6c, + 0x65, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2b, 0x0a, 0x11, + 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, + 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x49, + 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x3d, 0x0a, 0x1b, 0x62, 0x75, 0x6e, + 0x64, 0x6c, 0x65, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x18, + 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x53, 0x68, 0x6f, 0x72, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, + 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x2b, 0x0a, 0x11, 0x62, 0x75, 0x6e, 0x64, + 0x6c, 0x65, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x10, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x45, 0x78, 0x65, 0x63, 0x75, + 0x74, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x5f, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x62, 0x75, 0x6e, 0x64, + 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2e, 0x0a, 0x13, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, + 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x11, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x50, 0x61, 0x63, 0x6b, 0x61, + 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, + 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0f, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x62, 0x75, 0x6e, 0x64, 0x6c, + 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x64, + 0x75, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x72, + 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x75, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x55, 0x72, 0x6c, 0x22, 0x4c, 0x0a, 0x13, 0x53, 0x50, 0x44, 0x58, 0x50, 0x61, + 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x21, 0x0a, + 0x04, 0x70, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x73, 0x63, + 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2e, 0x50, 0x75, 0x72, 0x6c, 0x52, 0x04, 0x70, 0x75, 0x72, 0x6c, + 0x12, 0x12, 0x0a, 0x04, 0x63, 0x70, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, + 0x63, 0x70, 0x65, 0x73, 0x22, 0x4b, 0x0a, 0x12, 0x43, 0x44, 0x58, 0x50, 0x61, 0x63, 0x6b, 0x61, + 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x21, 0x0a, 0x04, 0x70, 0x75, + 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x73, 0x63, 0x61, 0x6c, 0x69, + 0x62, 0x72, 0x2e, 0x50, 0x75, 0x72, 0x6c, 0x52, 0x04, 0x70, 0x75, 0x72, 0x6c, 0x12, 0x12, 0x0a, + 0x04, 0x63, 0x70, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x63, 0x70, 0x65, + 0x73, 0x22, 0x65, 0x0a, 0x13, 0x4a, 0x61, 0x76, 0x61, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x72, 0x74, 0x69, + 0x66, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, + 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x67, 0x72, 0x6f, + 0x75, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x67, 0x72, 0x6f, + 0x75, 0x70, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x68, 0x61, 0x31, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x73, 0x68, 0x61, 0x31, 0x22, 0x78, 0x0a, 0x14, 0x4a, 0x61, 0x76, 0x61, + 0x4c, 0x6f, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x49, + 0x64, 0x12, 0x19, 0x0a, 0x08, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, + 0x64, 0x65, 0x70, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x76, 0x61, 0x6c, 0x73, 0x18, 0x03, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x64, 0x65, 0x70, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x56, 0x61, + 0x6c, 0x73, 0x22, 0x86, 0x01, 0x0a, 0x12, 0x4f, 0x53, 0x56, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, + 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x75, 0x72, + 0x6c, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x75, + 0x72, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x12, 0x1c, + 0x0a, 0x09, 0x65, 0x63, 0x6f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x65, 0x63, 0x6f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x1d, 0x0a, 0x0a, + 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x65, 0x5f, 0x61, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x65, 0x41, 0x73, 0x22, 0x86, 0x01, 0x0a, 0x1a, + 0x50, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, + 0x74, 0x73, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x39, 0x0a, 0x19, 0x68, 0x61, + 0x73, 0x68, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x5f, 0x6d, 0x6f, 0x64, 0x65, + 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x16, 0x68, + 0x61, 0x73, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x4d, 0x6f, 0x64, 0x65, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x2d, 0x0a, 0x12, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x11, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, + 0x61, 0x74, 0x6f, 0x72, 0x22, 0x44, 0x0a, 0x13, 0x50, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x53, 0x65, + 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x2d, 0x0a, 0x12, 0x76, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x61, 0x74, 0x6f, + 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x22, 0xf7, 0x02, 0x0a, 0x1b, 0x43, + 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x25, 0x0a, 0x0e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4e, 0x61, 0x6d, @@ -4380,23 +4436,47 @@ var file_proto_scan_result_proto_rawDesc = []byte{ 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x0e, 0x0a, - 0x02, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x10, 0x0a, - 0x03, 0x70, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x70, 0x69, 0x64, 0x12, - 0x1f, 0x0a, 0x0b, 0x72, 0x6f, 0x6f, 0x74, 0x66, 0x73, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x07, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x6f, 0x6f, 0x74, 0x66, 0x73, 0x50, 0x61, 0x74, 0x68, - 0x22, 0x4f, 0x0a, 0x10, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x4f, 0x53, 0x56, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x12, 0x21, - 0x0a, 0x0c, 0x66, 0x75, 0x6c, 0x6c, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x66, 0x75, 0x6c, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 0x22, 0x19, 0x0a, 0x17, 0x48, 0x6f, 0x6d, 0x65, 0x62, 0x72, 0x65, 0x77, 0x50, 0x61, 0x63, - 0x6b, 0x61, 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x42, 0x3f, 0x50, 0x01, - 0x5a, 0x3b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2f, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2f, 0x62, 0x69, 0x6e, 0x61, - 0x72, 0x79, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x63, 0x61, 0x6e, 0x5f, 0x72, 0x65, - 0x73, 0x75, 0x6c, 0x74, 0x5f, 0x67, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x10, 0x0a, + 0x03, 0x70, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x70, 0x69, 0x64, 0x12, + 0x20, 0x0a, 0x0b, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x74, 0x65, 0x72, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x74, 0x65, + 0x72, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5f, 0x6b, 0x65, + 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, + 0x74, 0x4b, 0x65, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x5f, 0x64, 0x69, + 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x44, 0x69, + 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x75, 0x70, 0x70, 0x65, 0x72, 0x5f, 0x64, 0x69, 0x72, 0x18, 0x09, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x70, 0x70, 0x65, 0x72, 0x44, 0x69, 0x72, 0x12, 0x19, + 0x0a, 0x08, 0x77, 0x6f, 0x72, 0x6b, 0x5f, 0x64, 0x69, 0x72, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x77, 0x6f, 0x72, 0x6b, 0x44, 0x69, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, + 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x70, 0x6f, 0x64, + 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x6f, 0x64, + 0x4e, 0x61, 0x6d, 0x65, 0x22, 0xea, 0x01, 0x0a, 0x22, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x65, 0x72, 0x64, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, + 0x6e, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x25, 0x0a, 0x0e, 0x6e, + 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4e, 0x61, + 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, + 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, + 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x44, 0x69, + 0x67, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x0e, + 0x0a, 0x02, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x10, + 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x70, 0x69, 0x64, + 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x6f, 0x6f, 0x74, 0x66, 0x73, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x6f, 0x6f, 0x74, 0x66, 0x73, 0x50, 0x61, 0x74, + 0x68, 0x22, 0x4f, 0x0a, 0x10, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x4f, 0x53, 0x56, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x12, + 0x21, 0x0a, 0x0c, 0x66, 0x75, 0x6c, 0x6c, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x66, 0x75, 0x6c, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, + 0x6f, 0x6e, 0x22, 0x19, 0x0a, 0x17, 0x48, 0x6f, 0x6d, 0x65, 0x62, 0x72, 0x65, 0x77, 0x50, 0x61, + 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x42, 0x3f, 0x50, + 0x01, 0x5a, 0x3b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x62, 0x72, 0x2f, 0x62, 0x69, 0x6e, + 0x61, 0x72, 0x79, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x63, 0x61, 0x6e, 0x5f, 0x72, + 0x65, 0x73, 0x75, 0x6c, 0x74, 0x5f, 0x67, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -4412,110 +4492,114 @@ func file_proto_scan_result_proto_rawDescGZIP() []byte { } var file_proto_scan_result_proto_enumTypes = make([]protoimpl.EnumInfo, 4) -var file_proto_scan_result_proto_msgTypes = make([]protoimpl.MessageInfo, 40) +var file_proto_scan_result_proto_msgTypes = make([]protoimpl.MessageInfo, 41) var file_proto_scan_result_proto_goTypes = []any{ (ScanStatus_ScanStatusEnum)(0), // 0: scalibr.ScanStatus.ScanStatusEnum - (Inventory_AnnotationEnum)(0), // 1: scalibr.Inventory.AnnotationEnum + (Package_AnnotationEnum)(0), // 1: scalibr.Package.AnnotationEnum (Advisory_TypeEnum)(0), // 2: scalibr.Advisory.TypeEnum (Severity_SeverityEnum)(0), // 3: scalibr.Severity.SeverityEnum (*ScanResult)(nil), // 4: scalibr.ScanResult - (*ScanStatus)(nil), // 5: scalibr.ScanStatus - (*PluginStatus)(nil), // 6: scalibr.PluginStatus - (*Inventory)(nil), // 7: scalibr.Inventory - (*SourceCodeIdentifier)(nil), // 8: scalibr.SourceCodeIdentifier - (*LayerDetails)(nil), // 9: scalibr.LayerDetails - (*Purl)(nil), // 10: scalibr.Purl - (*Qualifier)(nil), // 11: scalibr.Qualifier - (*Finding)(nil), // 12: scalibr.Finding - (*Advisory)(nil), // 13: scalibr.Advisory - (*AdvisoryId)(nil), // 14: scalibr.AdvisoryId - (*Severity)(nil), // 15: scalibr.Severity - (*CVSS)(nil), // 16: scalibr.CVSS - (*TargetDetails)(nil), // 17: scalibr.TargetDetails - (*PythonPackageMetadata)(nil), // 18: scalibr.PythonPackageMetadata - (*JavascriptPackageJSONMetadata)(nil), // 19: scalibr.JavascriptPackageJSONMetadata - (*APKPackageMetadata)(nil), // 20: scalibr.APKPackageMetadata - (*DPKGPackageMetadata)(nil), // 21: scalibr.DPKGPackageMetadata - (*RPMPackageMetadata)(nil), // 22: scalibr.RPMPackageMetadata - (*COSPackageMetadata)(nil), // 23: scalibr.COSPackageMetadata - (*PACMANPackageMetadata)(nil), // 24: scalibr.PACMANPackageMetadata - (*NixPackageMetadata)(nil), // 25: scalibr.NixPackageMetadata - (*DEPSJSONMetadata)(nil), // 26: scalibr.DEPSJSONMetadata - (*SNAPPackageMetadata)(nil), // 27: scalibr.SNAPPackageMetadata - (*PortagePackageMetadata)(nil), // 28: scalibr.PortagePackageMetadata - (*FlatpakPackageMetadata)(nil), // 29: scalibr.FlatpakPackageMetadata - (*KernelModuleMetadata)(nil), // 30: scalibr.KernelModuleMetadata - (*VmlinuzMetadata)(nil), // 31: scalibr.VmlinuzMetadata - (*MacAppsMetadata)(nil), // 32: scalibr.MacAppsMetadata - (*SPDXPackageMetadata)(nil), // 33: scalibr.SPDXPackageMetadata - (*CDXPackageMetadata)(nil), // 34: scalibr.CDXPackageMetadata - (*JavaArchiveMetadata)(nil), // 35: scalibr.JavaArchiveMetadata - (*JavaLockfileMetadata)(nil), // 36: scalibr.JavaLockfileMetadata - (*OSVPackageMetadata)(nil), // 37: scalibr.OSVPackageMetadata - (*PythonRequirementsMetadata)(nil), // 38: scalibr.PythonRequirementsMetadata - (*PythonSetupMetadata)(nil), // 39: scalibr.PythonSetupMetadata - (*ContainerdContainerMetadata)(nil), // 40: scalibr.ContainerdContainerMetadata - (*ContainerdRuntimeContainerMetadata)(nil), // 41: scalibr.ContainerdRuntimeContainerMetadata - (*WindowsOSVersion)(nil), // 42: scalibr.WindowsOSVersion - (*HomebrewPackageMetadata)(nil), // 43: scalibr.HomebrewPackageMetadata - (*timestamppb.Timestamp)(nil), // 44: google.protobuf.Timestamp + (*Inventory)(nil), // 5: scalibr.Inventory + (*ScanStatus)(nil), // 6: scalibr.ScanStatus + (*PluginStatus)(nil), // 7: scalibr.PluginStatus + (*Package)(nil), // 8: scalibr.Package + (*SourceCodeIdentifier)(nil), // 9: scalibr.SourceCodeIdentifier + (*LayerDetails)(nil), // 10: scalibr.LayerDetails + (*Purl)(nil), // 11: scalibr.Purl + (*Qualifier)(nil), // 12: scalibr.Qualifier + (*Finding)(nil), // 13: scalibr.Finding + (*Advisory)(nil), // 14: scalibr.Advisory + (*AdvisoryId)(nil), // 15: scalibr.AdvisoryId + (*Severity)(nil), // 16: scalibr.Severity + (*CVSS)(nil), // 17: scalibr.CVSS + (*TargetDetails)(nil), // 18: scalibr.TargetDetails + (*PythonPackageMetadata)(nil), // 19: scalibr.PythonPackageMetadata + (*JavascriptPackageJSONMetadata)(nil), // 20: scalibr.JavascriptPackageJSONMetadata + (*APKPackageMetadata)(nil), // 21: scalibr.APKPackageMetadata + (*DPKGPackageMetadata)(nil), // 22: scalibr.DPKGPackageMetadata + (*RPMPackageMetadata)(nil), // 23: scalibr.RPMPackageMetadata + (*COSPackageMetadata)(nil), // 24: scalibr.COSPackageMetadata + (*PACMANPackageMetadata)(nil), // 25: scalibr.PACMANPackageMetadata + (*NixPackageMetadata)(nil), // 26: scalibr.NixPackageMetadata + (*DEPSJSONMetadata)(nil), // 27: scalibr.DEPSJSONMetadata + (*SNAPPackageMetadata)(nil), // 28: scalibr.SNAPPackageMetadata + (*PortagePackageMetadata)(nil), // 29: scalibr.PortagePackageMetadata + (*FlatpakPackageMetadata)(nil), // 30: scalibr.FlatpakPackageMetadata + (*KernelModuleMetadata)(nil), // 31: scalibr.KernelModuleMetadata + (*VmlinuzMetadata)(nil), // 32: scalibr.VmlinuzMetadata + (*MacAppsMetadata)(nil), // 33: scalibr.MacAppsMetadata + (*SPDXPackageMetadata)(nil), // 34: scalibr.SPDXPackageMetadata + (*CDXPackageMetadata)(nil), // 35: scalibr.CDXPackageMetadata + (*JavaArchiveMetadata)(nil), // 36: scalibr.JavaArchiveMetadata + (*JavaLockfileMetadata)(nil), // 37: scalibr.JavaLockfileMetadata + (*OSVPackageMetadata)(nil), // 38: scalibr.OSVPackageMetadata + (*PythonRequirementsMetadata)(nil), // 39: scalibr.PythonRequirementsMetadata + (*PythonSetupMetadata)(nil), // 40: scalibr.PythonSetupMetadata + (*ContainerdContainerMetadata)(nil), // 41: scalibr.ContainerdContainerMetadata + (*ContainerdRuntimeContainerMetadata)(nil), // 42: scalibr.ContainerdRuntimeContainerMetadata + (*WindowsOSVersion)(nil), // 43: scalibr.WindowsOSVersion + (*HomebrewPackageMetadata)(nil), // 44: scalibr.HomebrewPackageMetadata + (*timestamppb.Timestamp)(nil), // 45: google.protobuf.Timestamp } var file_proto_scan_result_proto_depIdxs = []int32{ - 44, // 0: scalibr.ScanResult.start_time:type_name -> google.protobuf.Timestamp - 44, // 1: scalibr.ScanResult.end_time:type_name -> google.protobuf.Timestamp - 5, // 2: scalibr.ScanResult.status:type_name -> scalibr.ScanStatus - 6, // 3: scalibr.ScanResult.plugin_status:type_name -> scalibr.PluginStatus - 7, // 4: scalibr.ScanResult.inventories:type_name -> scalibr.Inventory - 12, // 5: scalibr.ScanResult.findings:type_name -> scalibr.Finding - 0, // 6: scalibr.ScanStatus.status:type_name -> scalibr.ScanStatus.ScanStatusEnum - 5, // 7: scalibr.PluginStatus.status:type_name -> scalibr.ScanStatus - 8, // 8: scalibr.Inventory.source_code:type_name -> scalibr.SourceCodeIdentifier - 10, // 9: scalibr.Inventory.purl:type_name -> scalibr.Purl - 18, // 10: scalibr.Inventory.python_metadata:type_name -> scalibr.PythonPackageMetadata - 19, // 11: scalibr.Inventory.javascript_metadata:type_name -> scalibr.JavascriptPackageJSONMetadata - 20, // 12: scalibr.Inventory.apk_metadata:type_name -> scalibr.APKPackageMetadata - 21, // 13: scalibr.Inventory.dpkg_metadata:type_name -> scalibr.DPKGPackageMetadata - 22, // 14: scalibr.Inventory.rpm_metadata:type_name -> scalibr.RPMPackageMetadata - 23, // 15: scalibr.Inventory.cos_metadata:type_name -> scalibr.COSPackageMetadata - 26, // 16: scalibr.Inventory.depsjson_metadata:type_name -> scalibr.DEPSJSONMetadata - 33, // 17: scalibr.Inventory.spdx_metadata:type_name -> scalibr.SPDXPackageMetadata - 35, // 18: scalibr.Inventory.java_archive_metadata:type_name -> scalibr.JavaArchiveMetadata - 36, // 19: scalibr.Inventory.java_lockfile_metadata:type_name -> scalibr.JavaLockfileMetadata - 24, // 20: scalibr.Inventory.pacman_metadata:type_name -> scalibr.PACMANPackageMetadata - 25, // 21: scalibr.Inventory.nix_metadata:type_name -> scalibr.NixPackageMetadata - 30, // 22: scalibr.Inventory.kernel_module_metadata:type_name -> scalibr.KernelModuleMetadata - 31, // 23: scalibr.Inventory.vmlinuz_metadata:type_name -> scalibr.VmlinuzMetadata - 28, // 24: scalibr.Inventory.portage_metadata:type_name -> scalibr.PortagePackageMetadata - 37, // 25: scalibr.Inventory.osv_metadata:type_name -> scalibr.OSVPackageMetadata - 38, // 26: scalibr.Inventory.python_requirements_metadata:type_name -> scalibr.PythonRequirementsMetadata - 39, // 27: scalibr.Inventory.python_setup_metadata:type_name -> scalibr.PythonSetupMetadata - 40, // 28: scalibr.Inventory.containerd_container_metadata:type_name -> scalibr.ContainerdContainerMetadata - 27, // 29: scalibr.Inventory.snap_metadata:type_name -> scalibr.SNAPPackageMetadata - 29, // 30: scalibr.Inventory.flatpak_metadata:type_name -> scalibr.FlatpakPackageMetadata - 32, // 31: scalibr.Inventory.mac_apps_metadata:type_name -> scalibr.MacAppsMetadata - 41, // 32: scalibr.Inventory.containerd_runtime_container_metadata:type_name -> scalibr.ContainerdRuntimeContainerMetadata - 34, // 33: scalibr.Inventory.cdx_metadata:type_name -> scalibr.CDXPackageMetadata - 42, // 34: scalibr.Inventory.windows_os_version_metadata:type_name -> scalibr.WindowsOSVersion - 43, // 35: scalibr.Inventory.homebrew_metadata:type_name -> scalibr.HomebrewPackageMetadata - 1, // 36: scalibr.Inventory.annotations:type_name -> scalibr.Inventory.AnnotationEnum - 9, // 37: scalibr.Inventory.layer_details:type_name -> scalibr.LayerDetails - 11, // 38: scalibr.Purl.qualifiers:type_name -> scalibr.Qualifier - 13, // 39: scalibr.Finding.adv:type_name -> scalibr.Advisory - 17, // 40: scalibr.Finding.target:type_name -> scalibr.TargetDetails - 14, // 41: scalibr.Advisory.id:type_name -> scalibr.AdvisoryId - 2, // 42: scalibr.Advisory.type:type_name -> scalibr.Advisory.TypeEnum - 15, // 43: scalibr.Advisory.sev:type_name -> scalibr.Severity - 3, // 44: scalibr.Severity.severity:type_name -> scalibr.Severity.SeverityEnum - 16, // 45: scalibr.Severity.cvss_v2:type_name -> scalibr.CVSS - 16, // 46: scalibr.Severity.cvss_v3:type_name -> scalibr.CVSS - 7, // 47: scalibr.TargetDetails.inventory:type_name -> scalibr.Inventory - 10, // 48: scalibr.SPDXPackageMetadata.purl:type_name -> scalibr.Purl - 10, // 49: scalibr.CDXPackageMetadata.purl:type_name -> scalibr.Purl - 50, // [50:50] is the sub-list for method output_type - 50, // [50:50] is the sub-list for method input_type - 50, // [50:50] is the sub-list for extension type_name - 50, // [50:50] is the sub-list for extension extendee - 0, // [0:50] is the sub-list for field type_name + 45, // 0: scalibr.ScanResult.start_time:type_name -> google.protobuf.Timestamp + 45, // 1: scalibr.ScanResult.end_time:type_name -> google.protobuf.Timestamp + 6, // 2: scalibr.ScanResult.status:type_name -> scalibr.ScanStatus + 7, // 3: scalibr.ScanResult.plugin_status:type_name -> scalibr.PluginStatus + 8, // 4: scalibr.ScanResult.inventories_deprecated:type_name -> scalibr.Package + 13, // 5: scalibr.ScanResult.findings_deprecated:type_name -> scalibr.Finding + 5, // 6: scalibr.ScanResult.inventory:type_name -> scalibr.Inventory + 8, // 7: scalibr.Inventory.packages:type_name -> scalibr.Package + 13, // 8: scalibr.Inventory.findings:type_name -> scalibr.Finding + 0, // 9: scalibr.ScanStatus.status:type_name -> scalibr.ScanStatus.ScanStatusEnum + 6, // 10: scalibr.PluginStatus.status:type_name -> scalibr.ScanStatus + 9, // 11: scalibr.Package.source_code:type_name -> scalibr.SourceCodeIdentifier + 11, // 12: scalibr.Package.purl:type_name -> scalibr.Purl + 19, // 13: scalibr.Package.python_metadata:type_name -> scalibr.PythonPackageMetadata + 20, // 14: scalibr.Package.javascript_metadata:type_name -> scalibr.JavascriptPackageJSONMetadata + 21, // 15: scalibr.Package.apk_metadata:type_name -> scalibr.APKPackageMetadata + 22, // 16: scalibr.Package.dpkg_metadata:type_name -> scalibr.DPKGPackageMetadata + 23, // 17: scalibr.Package.rpm_metadata:type_name -> scalibr.RPMPackageMetadata + 24, // 18: scalibr.Package.cos_metadata:type_name -> scalibr.COSPackageMetadata + 27, // 19: scalibr.Package.depsjson_metadata:type_name -> scalibr.DEPSJSONMetadata + 34, // 20: scalibr.Package.spdx_metadata:type_name -> scalibr.SPDXPackageMetadata + 36, // 21: scalibr.Package.java_archive_metadata:type_name -> scalibr.JavaArchiveMetadata + 37, // 22: scalibr.Package.java_lockfile_metadata:type_name -> scalibr.JavaLockfileMetadata + 25, // 23: scalibr.Package.pacman_metadata:type_name -> scalibr.PACMANPackageMetadata + 26, // 24: scalibr.Package.nix_metadata:type_name -> scalibr.NixPackageMetadata + 31, // 25: scalibr.Package.kernel_module_metadata:type_name -> scalibr.KernelModuleMetadata + 32, // 26: scalibr.Package.vmlinuz_metadata:type_name -> scalibr.VmlinuzMetadata + 29, // 27: scalibr.Package.portage_metadata:type_name -> scalibr.PortagePackageMetadata + 38, // 28: scalibr.Package.osv_metadata:type_name -> scalibr.OSVPackageMetadata + 39, // 29: scalibr.Package.python_requirements_metadata:type_name -> scalibr.PythonRequirementsMetadata + 40, // 30: scalibr.Package.python_setup_metadata:type_name -> scalibr.PythonSetupMetadata + 41, // 31: scalibr.Package.containerd_container_metadata:type_name -> scalibr.ContainerdContainerMetadata + 28, // 32: scalibr.Package.snap_metadata:type_name -> scalibr.SNAPPackageMetadata + 30, // 33: scalibr.Package.flatpak_metadata:type_name -> scalibr.FlatpakPackageMetadata + 33, // 34: scalibr.Package.mac_apps_metadata:type_name -> scalibr.MacAppsMetadata + 42, // 35: scalibr.Package.containerd_runtime_container_metadata:type_name -> scalibr.ContainerdRuntimeContainerMetadata + 35, // 36: scalibr.Package.cdx_metadata:type_name -> scalibr.CDXPackageMetadata + 43, // 37: scalibr.Package.windows_os_version_metadata:type_name -> scalibr.WindowsOSVersion + 44, // 38: scalibr.Package.homebrew_metadata:type_name -> scalibr.HomebrewPackageMetadata + 1, // 39: scalibr.Package.annotations:type_name -> scalibr.Package.AnnotationEnum + 10, // 40: scalibr.Package.layer_details:type_name -> scalibr.LayerDetails + 12, // 41: scalibr.Purl.qualifiers:type_name -> scalibr.Qualifier + 14, // 42: scalibr.Finding.adv:type_name -> scalibr.Advisory + 18, // 43: scalibr.Finding.target:type_name -> scalibr.TargetDetails + 15, // 44: scalibr.Advisory.id:type_name -> scalibr.AdvisoryId + 2, // 45: scalibr.Advisory.type:type_name -> scalibr.Advisory.TypeEnum + 16, // 46: scalibr.Advisory.sev:type_name -> scalibr.Severity + 3, // 47: scalibr.Severity.severity:type_name -> scalibr.Severity.SeverityEnum + 17, // 48: scalibr.Severity.cvss_v2:type_name -> scalibr.CVSS + 17, // 49: scalibr.Severity.cvss_v3:type_name -> scalibr.CVSS + 8, // 50: scalibr.TargetDetails.package:type_name -> scalibr.Package + 11, // 51: scalibr.SPDXPackageMetadata.purl:type_name -> scalibr.Purl + 11, // 52: scalibr.CDXPackageMetadata.purl:type_name -> scalibr.Purl + 53, // [53:53] is the sub-list for method output_type + 53, // [53:53] is the sub-list for method input_type + 53, // [53:53] is the sub-list for extension type_name + 53, // [53:53] is the sub-list for extension extendee + 0, // [0:53] is the sub-list for field type_name } func init() { file_proto_scan_result_proto_init() } @@ -4523,33 +4607,33 @@ func file_proto_scan_result_proto_init() { if File_proto_scan_result_proto != nil { return } - file_proto_scan_result_proto_msgTypes[3].OneofWrappers = []any{ - (*Inventory_PythonMetadata)(nil), - (*Inventory_JavascriptMetadata)(nil), - (*Inventory_ApkMetadata)(nil), - (*Inventory_DpkgMetadata)(nil), - (*Inventory_RpmMetadata)(nil), - (*Inventory_CosMetadata)(nil), - (*Inventory_DepsjsonMetadata)(nil), - (*Inventory_SpdxMetadata)(nil), - (*Inventory_JavaArchiveMetadata)(nil), - (*Inventory_JavaLockfileMetadata)(nil), - (*Inventory_PacmanMetadata)(nil), - (*Inventory_NixMetadata)(nil), - (*Inventory_KernelModuleMetadata)(nil), - (*Inventory_VmlinuzMetadata)(nil), - (*Inventory_PortageMetadata)(nil), - (*Inventory_OsvMetadata)(nil), - (*Inventory_PythonRequirementsMetadata)(nil), - (*Inventory_PythonSetupMetadata)(nil), - (*Inventory_ContainerdContainerMetadata)(nil), - (*Inventory_SnapMetadata)(nil), - (*Inventory_FlatpakMetadata)(nil), - (*Inventory_MacAppsMetadata)(nil), - (*Inventory_ContainerdRuntimeContainerMetadata)(nil), - (*Inventory_CdxMetadata)(nil), - (*Inventory_WindowsOsVersionMetadata)(nil), - (*Inventory_HomebrewMetadata)(nil), + file_proto_scan_result_proto_msgTypes[4].OneofWrappers = []any{ + (*Package_PythonMetadata)(nil), + (*Package_JavascriptMetadata)(nil), + (*Package_ApkMetadata)(nil), + (*Package_DpkgMetadata)(nil), + (*Package_RpmMetadata)(nil), + (*Package_CosMetadata)(nil), + (*Package_DepsjsonMetadata)(nil), + (*Package_SpdxMetadata)(nil), + (*Package_JavaArchiveMetadata)(nil), + (*Package_JavaLockfileMetadata)(nil), + (*Package_PacmanMetadata)(nil), + (*Package_NixMetadata)(nil), + (*Package_KernelModuleMetadata)(nil), + (*Package_VmlinuzMetadata)(nil), + (*Package_PortageMetadata)(nil), + (*Package_OsvMetadata)(nil), + (*Package_PythonRequirementsMetadata)(nil), + (*Package_PythonSetupMetadata)(nil), + (*Package_ContainerdContainerMetadata)(nil), + (*Package_SnapMetadata)(nil), + (*Package_FlatpakMetadata)(nil), + (*Package_MacAppsMetadata)(nil), + (*Package_ContainerdRuntimeContainerMetadata)(nil), + (*Package_CdxMetadata)(nil), + (*Package_WindowsOsVersionMetadata)(nil), + (*Package_HomebrewMetadata)(nil), } type x struct{} out := protoimpl.TypeBuilder{ @@ -4557,7 +4641,7 @@ func file_proto_scan_result_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_proto_scan_result_proto_rawDesc, NumEnums: 4, - NumMessages: 40, + NumMessages: 41, NumExtensions: 0, NumServices: 0, }, diff --git a/binary/scanrunner/scanrunner.go b/binary/scanrunner/scanrunner.go index 55add2e6..8d9025e9 100644 --- a/binary/scanrunner/scanrunner.go +++ b/binary/scanrunner/scanrunner.go @@ -48,7 +48,7 @@ func RunScan(flags *cli.Flags) int { result := scalibr.New().Scan(context.Background(), cfg) log.Infof("Scan status: %v", result.Status) - log.Infof("Found %d software inventories, %d security findings", len(result.Inventories), len(result.Findings)) + log.Infof("Found %d software packages, %d security findings", len(result.Inventory.Packages), len(result.Inventory.Findings)) if err := flags.WriteScanResults(result); err != nil { log.Errorf("Error writing scan results: %v", err) diff --git a/binary/scanrunner/scanrunner_test.go b/binary/scanrunner/scanrunner_test.go index 422dbebc..0aadd2ad 100644 --- a/binary/scanrunner/scanrunner_test.go +++ b/binary/scanrunner/scanrunner_test.go @@ -77,39 +77,39 @@ func createFailingDetectorTestFiles(t *testing.T) string { func TestRunScan(t *testing.T) { testCases := []struct { - desc string - setupFunc func(t *testing.T) string - flags *cli.Flags - wantPluginStatus []spb.ScanStatus_ScanStatusEnum - wantInventoryCount int - wantFindingCount int - excludeOS []string // test will not run on these operating systems + desc string + setupFunc func(t *testing.T) string + flags *cli.Flags + wantPluginStatus []spb.ScanStatus_ScanStatusEnum + wantPackagesCount int + wantFindingCount int + excludeOS []string // test will not run on these operating systems }{ { - desc: "Successful detector run", - setupFunc: createDetectorTestFiles, - flags: &cli.Flags{DetectorsToRun: []string{"cis"}}, - wantPluginStatus: []spb.ScanStatus_ScanStatusEnum{spb.ScanStatus_SUCCEEDED}, - wantInventoryCount: 0, - wantFindingCount: 1, + desc: "Successful detector run", + setupFunc: createDetectorTestFiles, + flags: &cli.Flags{DetectorsToRun: []string{"cis"}}, + wantPluginStatus: []spb.ScanStatus_ScanStatusEnum{spb.ScanStatus_SUCCEEDED}, + wantPackagesCount: 0, + wantFindingCount: 1, // TODO: b/343368902: Fix once we have a detector for Windows. excludeOS: []string{"windows"}, }, { - desc: "Successful extractor run", - setupFunc: createExtractorTestFiles, - flags: &cli.Flags{ExtractorsToRun: []string{"python/wheelegg"}}, - wantPluginStatus: []spb.ScanStatus_ScanStatusEnum{spb.ScanStatus_SUCCEEDED}, - wantInventoryCount: 1, - wantFindingCount: 0, + desc: "Successful extractor run", + setupFunc: createExtractorTestFiles, + flags: &cli.Flags{ExtractorsToRun: []string{"python/wheelegg"}}, + wantPluginStatus: []spb.ScanStatus_ScanStatusEnum{spb.ScanStatus_SUCCEEDED}, + wantPackagesCount: 1, + wantFindingCount: 0, }, { - desc: "Unsuccessful plugin run", - setupFunc: createFailingDetectorTestFiles, - flags: &cli.Flags{DetectorsToRun: []string{"cis"}}, - wantPluginStatus: []spb.ScanStatus_ScanStatusEnum{spb.ScanStatus_FAILED}, - wantInventoryCount: 0, - wantFindingCount: 0, + desc: "Unsuccessful plugin run", + setupFunc: createFailingDetectorTestFiles, + flags: &cli.Flags{DetectorsToRun: []string{"cis"}}, + wantPluginStatus: []spb.ScanStatus_ScanStatusEnum{spb.ScanStatus_FAILED}, + wantPackagesCount: 0, + wantFindingCount: 0, // TODO: b/343368902: Fix once we have a detector for Windows. excludeOS: []string{"windows"}, }, @@ -149,11 +149,11 @@ func TestRunScan(t *testing.T) { if diff := cmp.Diff(tc.wantPluginStatus, gotPS); diff != "" { t.Errorf("Unexpected plugin status (-want +got):\n%s", diff) } - if len(result.Inventories) != tc.wantInventoryCount { - t.Errorf("Unexpected inventory count, want %d got %d", tc.wantInventoryCount, len(result.Inventories)) + if len(result.Inventory.Packages) != tc.wantPackagesCount { + t.Errorf("Unexpected package count, want %d got %d", tc.wantPackagesCount, len(result.Inventory.Packages)) } - if len(result.Findings) != tc.wantFindingCount { - t.Errorf("Unexpected finding count, want %d got %d", tc.wantFindingCount, len(result.Findings)) + if len(result.Inventory.Findings) != tc.wantFindingCount { + t.Errorf("Unexpected finding count, want %d got %d", tc.wantFindingCount, len(result.Inventory.Findings)) } }) } diff --git a/converter/converter.go b/converter/converter.go index 95c72975..0eb79bfc 100644 --- a/converter/converter.go +++ b/converter/converter.go @@ -13,7 +13,7 @@ // limitations under the License. // Package converter provides utility functions for converting SCALIBR's scan results to -// standardized inventory formats. +// standardized package formats. package converter import ( @@ -45,9 +45,9 @@ const ( // spdx_id must only contain letters, numbers, "." and "-" var spdxIDInvalidCharRe = regexp.MustCompile(`[^a-zA-Z0-9.-]`) -// ToPURL converts a SCALIBR inventory structure into a package URL. -func ToPURL(i *extractor.Inventory) *purl.PackageURL { - return i.Extractor.ToPURL(i) +// ToPURL converts a SCALIBR package structure into a package URL. +func ToPURL(p *extractor.Package) *purl.PackageURL { + return p.Extractor.ToPURL(p) } // SPDXConfig describes custom settings that should be applied to the generated SPDX file. @@ -59,7 +59,7 @@ type SPDXConfig struct { // ToSPDX23 converts the SCALIBR scan results into an SPDX v2.3 document. func ToSPDX23(r *scalibr.ScanResult, c SPDXConfig) *v2_3.Document { - packages := make([]*v2_3.Package, 0, len(r.Inventories)+1) + packages := make([]*v2_3.Package, 0, len(r.Inventory.Packages)+1) // Add a main package that contains all other top-level packages. mainPackageID := SPDXRefPrefix + "Package-main-" + uuid.New().String() @@ -75,31 +75,31 @@ func ToSPDX23(r *scalibr.ScanResult, c SPDXConfig) *v2_3.Document { IsFilesAnalyzedTagPresent: false, }) - relationships := make([]*v2_3.Relationship, 0, 1+2*len(r.Inventories)) + relationships := make([]*v2_3.Relationship, 0, 1+2*len(r.Inventory.Packages)) relationships = append(relationships, &v2_3.Relationship{ RefA: toDocElementID(SPDXDocumentID), RefB: toDocElementID(mainPackageID), Relationship: "DESCRIBES", }) - for _, i := range r.Inventories { - p := ToPURL(i) + for _, pkg := range r.Inventory.Packages { + p := ToPURL(pkg) if p == nil { - log.Warnf("Inventory %v has no PURL, skipping", i) + log.Warnf("Package %v has no PURL, skipping", pkg) continue } pName := p.Name pVersion := p.Version if pName == "" || pVersion == "" { - log.Warnf("Inventory %v PURL name or version empty, skipping", i) + log.Warnf("Package %v PURL name or version empty, skipping", pkg) continue } pID := SPDXRefPrefix + "Package-" + replaceSPDXIDInvalidChars(pName) + "-" + uuid.New().String() - pSourceInfo := fmt.Sprintf("Identified by the %s extractor", i.Extractor.Name()) - if len(i.Locations) == 1 { - pSourceInfo += fmt.Sprintf(" from %s", i.Locations[0]) - } else if l := len(i.Locations); l > 1 { - pSourceInfo += fmt.Sprintf(" from %d locations, including %s and %s", l, i.Locations[0], i.Locations[1]) + pSourceInfo := fmt.Sprintf("Identified by the %s extractor", pkg.Extractor.Name()) + if len(pkg.Locations) == 1 { + pSourceInfo += fmt.Sprintf(" from %s", pkg.Locations[0]) + } else if l := len(pkg.Locations); l > 1 { + pSourceInfo += fmt.Sprintf(" from %d locations, including %s and %s", l, pkg.Locations[0], pkg.Locations[1]) } packages = append(packages, &v2_3.Package{ @@ -220,44 +220,44 @@ func ToCDX(r *scalibr.ScanResult, c CDXConfig) *cyclonedx.BOM { bom.Metadata.Authors = &authors } - comps := make([]cyclonedx.Component, 0, len(r.Inventories)) - for _, i := range r.Inventories { - pkg := cyclonedx.Component{ + comps := make([]cyclonedx.Component, 0, len(r.Inventory.Packages)) + for _, pkg := range r.Inventory.Packages { + comp := cyclonedx.Component{ BOMRef: uuid.New().String(), Type: cyclonedx.ComponentTypeLibrary, - Name: (*i).Name, - Version: (*i).Version, + Name: (*pkg).Name, + Version: (*pkg).Version, } - if p := ToPURL(i); p != nil { - pkg.PackageURL = p.String() + if p := ToPURL(pkg); p != nil { + comp.PackageURL = p.String() } - if cpes := extractCPEs(i); len(cpes) > 0 { - pkg.CPE = cpes[0] + if cpes := extractCPEs(pkg); len(cpes) > 0 { + comp.CPE = cpes[0] } - if len((*i).Locations) > 0 { - occ := make([]cyclonedx.EvidenceOccurrence, 0, len(((*i).Locations))) - for _, loc := range (*i).Locations { + if len((*pkg).Locations) > 0 { + occ := make([]cyclonedx.EvidenceOccurrence, 0, len(((*pkg).Locations))) + for _, loc := range (*pkg).Locations { occ = append(occ, cyclonedx.EvidenceOccurrence{ Location: loc, }) } - pkg.Evidence = &cyclonedx.Evidence{ + comp.Evidence = &cyclonedx.Evidence{ Occurrences: &occ, } } - comps = append(comps, pkg) + comps = append(comps, comp) } bom.Components = &comps return bom } -func extractCPEs(i *extractor.Inventory) []string { - // Only the two SBOM inventory types support storing CPEs. - if m, ok := i.Metadata.(*spdxe.Metadata); ok { +func extractCPEs(p *extractor.Package) []string { + // Only the two SBOM package types support storing CPEs. + if m, ok := p.Metadata.(*spdxe.Metadata); ok { return m.CPEs } - if m, ok := i.Metadata.(*cdxe.Metadata); ok { + if m, ok := p.Metadata.(*cdxe.Metadata); ok { return m.CPEs } return nil diff --git a/converter/converter_test.go b/converter/converter_test.go index 813a7058..692f884b 100644 --- a/converter/converter_test.go +++ b/converter/converter_test.go @@ -45,9 +45,11 @@ func TestToSPDX23(t *testing.T) { { desc: "Package with no custom config", scanResult: &scalibr.ScanResult{ - Inventories: []*extractor.Inventory{{ - Name: "software", Version: "1.2.3", Extractor: pipEx, - }}, + Inventory: &scalibr.Inventory{ + Packages: []*extractor.Package{{ + Name: "software", Version: "1.2.3", Extractor: pipEx, + }}, + }, }, want: &v2_3.Document{ SPDXVersion: "SPDX-2.3", @@ -129,9 +131,11 @@ func TestToSPDX23(t *testing.T) { { desc: "Package with custom config", scanResult: &scalibr.ScanResult{ - Inventories: []*extractor.Inventory{{ - Name: "software", Version: "1.2.3", Extractor: pipEx, - }}, + Inventory: &scalibr.Inventory{ + Packages: []*extractor.Package{{ + Name: "software", Version: "1.2.3", Extractor: pipEx, + }}, + }, }, config: converter.SPDXConfig{ DocumentName: "Custom name", @@ -227,16 +231,18 @@ func TestToSPDX23(t *testing.T) { { desc: "Package with invalid PURLs skipped", scanResult: &scalibr.ScanResult{ - Inventories: []*extractor.Inventory{ - // PURL field missing - {Extractor: pipEx}, - // No name - { - Version: "1.2.3", Extractor: pipEx, - }, - // No version - { - Name: "software", Extractor: pipEx, + Inventory: &scalibr.Inventory{ + Packages: []*extractor.Package{ + // PURL field missing + {Extractor: pipEx}, + // No name + { + Version: "1.2.3", Extractor: pipEx, + }, + // No version + { + Name: "software", Extractor: pipEx, + }, }, }, }, @@ -281,9 +287,11 @@ func TestToSPDX23(t *testing.T) { { desc: "Invalid chars in package name replaced", scanResult: &scalibr.ScanResult{ - Inventories: []*extractor.Inventory{{ - Name: "softw@re&", Version: "1.2.3", Extractor: pipEx, - }}, + Inventory: &scalibr.Inventory{ + Packages: []*extractor.Package{{ + Name: "softw@re&", Version: "1.2.3", Extractor: pipEx, + }}, + }, }, want: &v2_3.Document{ SPDXVersion: "SPDX-2.3", @@ -365,9 +373,11 @@ func TestToSPDX23(t *testing.T) { { desc: "One location reported", scanResult: &scalibr.ScanResult{ - Inventories: []*extractor.Inventory{{ - Name: "software", Version: "1.2.3", Extractor: pipEx, Locations: []string{"/file1"}, - }}, + Inventory: &scalibr.Inventory{ + Packages: []*extractor.Package{{ + Name: "software", Version: "1.2.3", Extractor: pipEx, Locations: []string{"/file1"}, + }}, + }, }, want: &v2_3.Document{ SPDXVersion: "SPDX-2.3", @@ -449,9 +459,11 @@ func TestToSPDX23(t *testing.T) { { desc: "Multiple locations reported", scanResult: &scalibr.ScanResult{ - Inventories: []*extractor.Inventory{{ - Name: "software", Version: "1.2.3", Extractor: pipEx, Locations: []string{"/file1", "/file2", "/file3"}, - }}, + Inventory: &scalibr.Inventory{ + Packages: []*extractor.Package{{ + Name: "software", Version: "1.2.3", Extractor: pipEx, Locations: []string{"/file1", "/file2", "/file3"}, + }}, + }, }, want: &v2_3.Document{ SPDXVersion: "SPDX-2.3", @@ -564,9 +576,11 @@ func TestToCDX(t *testing.T) { { desc: "Package with custom config", scanResult: &scalibr.ScanResult{ - Inventories: []*extractor.Inventory{{ - Name: "software", Version: "1.2.3", Extractor: pipEx, - }}, + Inventory: &scalibr.Inventory{ + Packages: []*extractor.Package{{ + Name: "software", Version: "1.2.3", Extractor: pipEx, + }}, + }, }, config: converter.CDXConfig{ ComponentName: "sbom-1", @@ -628,14 +642,14 @@ func TestToCDX(t *testing.T) { func TestToPURL(t *testing.T) { pipEx := wheelegg.New(wheelegg.DefaultConfig()) tests := []struct { - desc string - inventory *extractor.Inventory - want *purl.PackageURL - onGoos string + desc string + pkg *extractor.Package + want *purl.PackageURL + onGoos string }{ { - desc: "Valid inventory extractor", - inventory: &extractor.Inventory{ + desc: "Valid package extractor", + pkg: &extractor.Package{ Name: "software", Version: "1.0.0", Locations: []string{"/file1"}, @@ -655,10 +669,10 @@ func TestToPURL(t *testing.T) { t.Skipf("Skipping test on %s", runtime.GOOS) } - got := converter.ToPURL(tc.inventory) + got := converter.ToPURL(tc.pkg) if diff := cmp.Diff(tc.want, got); diff != "" { - t.Errorf("converter.ToPURL(%v) returned unexpected diff (-want +got):\n%s", tc.inventory, diff) + t.Errorf("converter.ToPURL(%v) returned unexpected diff (-want +got):\n%s", tc.pkg, diff) } }) } diff --git a/detector/cis/generic_linux/etcpasswdpermissions/detector_dummy.go b/detector/cis/generic_linux/etcpasswdpermissions/detector_dummy.go index 4c2ee815..c0bf2e70 100644 --- a/detector/cis/generic_linux/etcpasswdpermissions/detector_dummy.go +++ b/detector/cis/generic_linux/etcpasswdpermissions/detector_dummy.go @@ -23,7 +23,7 @@ import ( "github.com/google/osv-scalibr/detector" scalibrfs "github.com/google/osv-scalibr/fs" - "github.com/google/osv-scalibr/inventoryindex" + "github.com/google/osv-scalibr/packageindex" "github.com/google/osv-scalibr/plugin" ) @@ -54,11 +54,11 @@ func (Detector) Requirements() *plugin.Capabilities { return &plugin.Capabilitie func (Detector) RequiredExtractors() []string { return []string{} } // Scan is a no-op for Windows. -func (d Detector) Scan(ctx context.Context, scanRoot *scalibrfs.ScanRoot, ix *inventoryindex.InventoryIndex) ([]*detector.Finding, error) { +func (d Detector) Scan(ctx context.Context, scanRoot *scalibrfs.ScanRoot, px *packageindex.PackageIndex) ([]*detector.Finding, error) { return nil, fmt.Errorf("plugin only supported on Linux") } // ScanFS starts the scan from a pseudo-filesystem. -func (Detector) ScanFS(ctx context.Context, fs fs.FS, ix *inventoryindex.InventoryIndex) ([]*detector.Finding, error) { +func (Detector) ScanFS(ctx context.Context, fs fs.FS, px *packageindex.PackageIndex) ([]*detector.Finding, error) { return nil, fmt.Errorf("plugin only supported on Linux") } diff --git a/detector/cis/generic_linux/etcpasswdpermissions/etcpasswdpermissions.go b/detector/cis/generic_linux/etcpasswdpermissions/etcpasswdpermissions.go index 44f41abc..214c48ed 100644 --- a/detector/cis/generic_linux/etcpasswdpermissions/etcpasswdpermissions.go +++ b/detector/cis/generic_linux/etcpasswdpermissions/etcpasswdpermissions.go @@ -27,7 +27,7 @@ import ( "github.com/google/osv-scalibr/detector" scalibrfs "github.com/google/osv-scalibr/fs" - "github.com/google/osv-scalibr/inventoryindex" + "github.com/google/osv-scalibr/packageindex" "github.com/google/osv-scalibr/plugin" ) @@ -58,12 +58,12 @@ func (Detector) RequiredExtractors() []string { return []string{} } func (Detector) Requirements() *plugin.Capabilities { return &plugin.Capabilities{OS: plugin.OSUnix} } // Scan starts the scan. -func (d Detector) Scan(ctx context.Context, scanRoot *scalibrfs.ScanRoot, ix *inventoryindex.InventoryIndex) ([]*detector.Finding, error) { - return d.ScanFS(ctx, scanRoot.FS, ix) +func (d Detector) Scan(ctx context.Context, scanRoot *scalibrfs.ScanRoot, px *packageindex.PackageIndex) ([]*detector.Finding, error) { + return d.ScanFS(ctx, scanRoot.FS, px) } // ScanFS starts the scan from a pseudo-filesystem. -func (Detector) ScanFS(ctx context.Context, fs fs.FS, ix *inventoryindex.InventoryIndex) ([]*detector.Finding, error) { +func (Detector) ScanFS(ctx context.Context, fs fs.FS, px *packageindex.PackageIndex) ([]*detector.Finding, error) { f, err := fs.Open("etc/passwd") if err != nil { if errors.Is(err, os.ErrNotExist) { diff --git a/detector/cis/generic_linux/etcpasswdpermissions/etcpasswdpermissions_test.go b/detector/cis/generic_linux/etcpasswdpermissions/etcpasswdpermissions_test.go index 78e8d82c..9fe902b3 100644 --- a/detector/cis/generic_linux/etcpasswdpermissions/etcpasswdpermissions_test.go +++ b/detector/cis/generic_linux/etcpasswdpermissions/etcpasswdpermissions_test.go @@ -27,7 +27,7 @@ import ( "github.com/google/osv-scalibr/detector/cis/generic_linux/etcpasswdpermissions" "github.com/google/osv-scalibr/extractor" scalibrfs "github.com/google/osv-scalibr/fs" - "github.com/google/osv-scalibr/inventoryindex" + "github.com/google/osv-scalibr/packageindex" ) // A fake implementation of fs.FS where the only file is /etc/passwd and it has configurable permissions. @@ -74,7 +74,7 @@ func TestScan(t *testing.T) { Sev: &detector.Severity{Severity: detector.SeverityMinimal}, } - ix, _ := inventoryindex.New([]*extractor.Inventory{}) + px, _ := packageindex.New([]*extractor.Package{}) testCases := []struct { desc string fsys scalibrfs.FS @@ -123,7 +123,7 @@ func TestScan(t *testing.T) { for _, tc := range testCases { t.Run(tc.desc, func(t *testing.T) { det := etcpasswdpermissions.Detector{} - findings, err := det.Scan(context.Background(), &scalibrfs.ScanRoot{FS: tc.fsys}, ix) + findings, err := det.Scan(context.Background(), &scalibrfs.ScanRoot{FS: tc.fsys}, px) if diff := cmp.Diff(tc.wantErr, err, cmpopts.EquateErrors()); diff != "" { t.Errorf("detector.Scan(%v): unexpected error (-want +got):\n%s", tc.fsys, diff) } diff --git a/detector/cve/cve202011978/cve202011978.go b/detector/cve/cve202011978/cve202011978.go index edd7f338..8b455091 100644 --- a/detector/cve/cve202011978/cve202011978.go +++ b/detector/cve/cve202011978/cve202011978.go @@ -34,13 +34,13 @@ import ( "github.com/google/osv-scalibr/extractor" "github.com/google/osv-scalibr/extractor/filesystem/language/python/wheelegg" scalibrfs "github.com/google/osv-scalibr/fs" - "github.com/google/osv-scalibr/inventoryindex" "github.com/google/osv-scalibr/log" + "github.com/google/osv-scalibr/packageindex" "github.com/google/osv-scalibr/plugin" ) type airflowPackageNames struct { - packageType string + pkgType string name string affectedVersions []string } @@ -61,8 +61,8 @@ var ( randFilePath = fmt.Sprintf("/tmp/%s", randomString(16)) airflowPackages = []airflowPackageNames{ { - packageType: "pypi", - name: "apache-airflow", + pkgType: "pypi", + name: "apache-airflow", affectedVersions: []string{ "1.10.10", "1.10.10rc5", @@ -143,18 +143,18 @@ func (Detector) Requirements() *plugin.Capabilities { // RequiredExtractors returns the python wheel extractor. func (Detector) RequiredExtractors() []string { return []string{wheelegg.Name} } -func findairflowVersions(ix *inventoryindex.InventoryIndex) (string, *extractor.Inventory, []string) { +func findairflowVersions(px *packageindex.PackageIndex) (string, *extractor.Package, []string) { for _, r := range airflowPackages { - for _, i := range ix.GetSpecific(r.name, r.packageType) { - return i.Version, i, r.affectedVersions + for _, p := range px.GetSpecific(r.name, r.pkgType) { + return p.Version, p, r.affectedVersions } } return "", nil, []string{} } // Scan checks for the presence of the airflow CVE-2020-11978 vulnerability on the filesystem. -func (d Detector) Scan(ctx context.Context, scanRoot *scalibrfs.ScanRoot, ix *inventoryindex.InventoryIndex) ([]*detector.Finding, error) { - airflowVersion, inventory, affectedVersions := findairflowVersions(ix) +func (d Detector) Scan(ctx context.Context, scanRoot *scalibrfs.ScanRoot, px *packageindex.PackageIndex) ([]*detector.Finding, error) { + airflowVersion, pkg, affectedVersions := findairflowVersions(px) if airflowVersion == "" { log.Debugf("No airflow version found") return nil, nil @@ -218,9 +218,9 @@ func (d Detector) Scan(ctx context.Context, scanRoot *scalibrfs.ScanRoot, ix *in Sev: &detector.Severity{Severity: detector.SeverityCritical}, }, Target: &detector.TargetDetails{ - Inventory: inventory, + Package: pkg, }, - Extra: fmt.Sprintf("%s %s %s", inventory.Name, inventory.Version, strings.Join(inventory.Locations, ", ")), + Extra: fmt.Sprintf("%s %s %s", pkg.Name, pkg.Version, strings.Join(pkg.Locations, ", ")), }}, nil } diff --git a/detector/cve/cve202016846/cve202016846.go b/detector/cve/cve202016846/cve202016846.go index bfd87f9d..2af46de1 100644 --- a/detector/cve/cve202016846/cve202016846.go +++ b/detector/cve/cve202016846/cve202016846.go @@ -44,13 +44,13 @@ import ( "github.com/google/osv-scalibr/extractor" "github.com/google/osv-scalibr/extractor/filesystem/language/python/wheelegg" scalibrfs "github.com/google/osv-scalibr/fs" - "github.com/google/osv-scalibr/inventoryindex" "github.com/google/osv-scalibr/log" + "github.com/google/osv-scalibr/packageindex" "github.com/google/osv-scalibr/plugin" ) type saltPackageNames struct { - packageType string + pkgType string name string affectedVersions []string } @@ -69,8 +69,8 @@ var ( randFilePath = fmt.Sprintf("/tmp/%s", randomString(16)) saltPackages = []saltPackageNames{ { - packageType: "pypi", - name: "salt", + pkgType: "pypi", + name: "salt", affectedVersions: []string{ "2015.8.10", "2015.8.13", @@ -117,19 +117,19 @@ func (Detector) Requirements() *plugin.Capabilities { // RequiredExtractors returns an empty list as there are no dependencies. func (Detector) RequiredExtractors() []string { return []string{wheelegg.Name} } -func findSaltVersions(ix *inventoryindex.InventoryIndex) (string, *extractor.Inventory, []string) { +func findSaltVersions(px *packageindex.PackageIndex) (string, *extractor.Package, []string) { for _, r := range saltPackages { - inventory := ix.GetSpecific(r.name, r.packageType) - for _, i := range inventory { - return i.Version, i, r.affectedVersions + pkgs := px.GetSpecific(r.name, r.pkgType) + for _, p := range pkgs { + return p.Version, p, r.affectedVersions } } return "", nil, []string{} } // Scan checks for the presence of the Salt CVE-2020-16846 vulnerability on the filesystem. -func (d Detector) Scan(ctx context.Context, scanRoot *scalibrfs.ScanRoot, ix *inventoryindex.InventoryIndex) ([]*detector.Finding, error) { - saltVersion, inventory, affectedVersions := findSaltVersions(ix) +func (d Detector) Scan(ctx context.Context, scanRoot *scalibrfs.ScanRoot, px *packageindex.PackageIndex) ([]*detector.Finding, error) { + saltVersion, pkg, affectedVersions := findSaltVersions(px) if saltVersion == "" { log.Debugf("No Salt version found") return nil, nil @@ -184,9 +184,9 @@ func (d Detector) Scan(ctx context.Context, scanRoot *scalibrfs.ScanRoot, ix *in Sev: &detector.Severity{Severity: detector.SeverityCritical}, }, Target: &detector.TargetDetails{ - Inventory: inventory, + Package: pkg, }, - Extra: fmt.Sprintf("%s %s %s", inventory.Name, inventory.Version, strings.Join(inventory.Locations, ", ")), + Extra: fmt.Sprintf("%s %s %s", pkg.Name, pkg.Version, strings.Join(pkg.Locations, ", ")), }}, nil } diff --git a/detector/cve/cve202233891/cve202233891.go b/detector/cve/cve202233891/cve202233891.go index f8e46f6a..901c38cc 100644 --- a/detector/cve/cve202233891/cve202233891.go +++ b/detector/cve/cve202233891/cve202233891.go @@ -33,13 +33,13 @@ import ( "github.com/google/osv-scalibr/extractor" "github.com/google/osv-scalibr/extractor/filesystem/language/python/wheelegg" scalibrfs "github.com/google/osv-scalibr/fs" - "github.com/google/osv-scalibr/inventoryindex" "github.com/google/osv-scalibr/log" + "github.com/google/osv-scalibr/packageindex" "github.com/google/osv-scalibr/plugin" ) type sparkUIPackageNames struct { - packageType string + pkgType string name string affectedVersions []string } @@ -56,8 +56,8 @@ var ( sparkServersPorts = []int{4040, 8080} sparkUIPackages = []sparkUIPackageNames{ { - packageType: "pypi", - name: "pyspark", + pkgType: "pypi", + name: "pyspark", affectedVersions: []string{ "3.0.0", "3.0.1", @@ -98,8 +98,8 @@ func (Detector) RequiredExtractors() []string { } // Scan scans for the vulnerability, doh! -func (d Detector) Scan(ctx context.Context, scanRoot *scalibrfs.ScanRoot, ix *inventoryindex.InventoryIndex) ([]*detector.Finding, error) { - sparkUIVersion, inventory, affectedVersions := findApacheSparkUIPackage(ix) +func (d Detector) Scan(ctx context.Context, scanRoot *scalibrfs.ScanRoot, px *packageindex.PackageIndex) ([]*detector.Finding, error) { + sparkUIVersion, pkg, affectedVersions := findApacheSparkUIPackage(px) if sparkUIVersion == "" { log.Debugf("No Apache Spark UI version found") return nil, nil @@ -156,9 +156,9 @@ func (d Detector) Scan(ctx context.Context, scanRoot *scalibrfs.ScanRoot, ix *in Sev: &detector.Severity{Severity: detector.SeverityCritical}, }, Target: &detector.TargetDetails{ - Inventory: inventory, + Package: pkg, }, - Extra: fmt.Sprintf("%s %s %s", inventory.Name, inventory.Version, strings.Join(inventory.Locations, ", ")), + Extra: fmt.Sprintf("%s %s %s", pkg.Name, pkg.Version, strings.Join(pkg.Locations, ", ")), }}, nil } @@ -180,11 +180,11 @@ func sparkUIHTTPQuery(ctx context.Context, sparkDomain string, sparkPort int, cm return resp.StatusCode } -func findApacheSparkUIPackage(ix *inventoryindex.InventoryIndex) (string, *extractor.Inventory, []string) { +func findApacheSparkUIPackage(px *packageindex.PackageIndex) (string, *extractor.Package, []string) { for _, r := range sparkUIPackages { - inventory := ix.GetSpecific(r.name, r.packageType) - for _, i := range inventory { - return i.Version, i, r.affectedVersions + pkgs := px.GetSpecific(r.name, r.pkgType) + for _, p := range pkgs { + return p.Version, p, r.affectedVersions } } return "", nil, []string{} diff --git a/detector/cve/cve202338408/cve202338408.go b/detector/cve/cve202338408/cve202338408.go index 6f0a7fd7..4b099e98 100644 --- a/detector/cve/cve202338408/cve202338408.go +++ b/detector/cve/cve202338408/cve202338408.go @@ -28,8 +28,8 @@ import ( "github.com/google/osv-scalibr/detector" "github.com/google/osv-scalibr/detector/cve/cve202338408/semantic" scalibrfs "github.com/google/osv-scalibr/fs" - "github.com/google/osv-scalibr/inventoryindex" "github.com/google/osv-scalibr/log" + "github.com/google/osv-scalibr/packageindex" "github.com/google/osv-scalibr/plugin" ) @@ -70,7 +70,7 @@ func (Detector) Requirements() *plugin.Capabilities { func (Detector) RequiredExtractors() []string { return []string{} } // Scan checks for the presence of the OpenSSH CVE-2023-38408 vulnerability on the filesystem. -func (d Detector) Scan(ctx context.Context, scanRoot *scalibrfs.ScanRoot, ix *inventoryindex.InventoryIndex) ([]*detector.Finding, error) { +func (d Detector) Scan(ctx context.Context, scanRoot *scalibrfs.ScanRoot, px *packageindex.PackageIndex) ([]*detector.Finding, error) { // 1. OpenSSH between and 5.5 and 9.3p1 (inclusive) openSSHVersion := getOpenSSHVersion() if openSSHVersion == "" { diff --git a/detector/cve/cve20236019/cve20236019.go b/detector/cve/cve20236019/cve20236019.go index 1ac3b2be..4c3e9f10 100644 --- a/detector/cve/cve20236019/cve20236019.go +++ b/detector/cve/cve20236019/cve20236019.go @@ -34,8 +34,8 @@ import ( "github.com/google/osv-scalibr/extractor" "github.com/google/osv-scalibr/extractor/filesystem/language/python/wheelegg" scalibrfs "github.com/google/osv-scalibr/fs" - "github.com/google/osv-scalibr/inventoryindex" "github.com/google/osv-scalibr/log" + "github.com/google/osv-scalibr/packageindex" "github.com/google/osv-scalibr/plugin" ) @@ -70,8 +70,8 @@ func (Detector) RequiredExtractors() []string { } // Scan scans for the vulnerability -func (d Detector) Scan(ctx context.Context, scanRoot *scalibrfs.ScanRoot, ix *inventoryindex.InventoryIndex) ([]*detector.Finding, error) { - rayVersion, inventory := findRayPackage(ix) +func (d Detector) Scan(ctx context.Context, scanRoot *scalibrfs.ScanRoot, px *packageindex.PackageIndex) ([]*detector.Finding, error) { + rayVersion, pkg := findRayPackage(px) if rayVersion == "" { log.Debugf("No Ray version found") return nil, nil @@ -111,17 +111,17 @@ func (d Detector) Scan(ctx context.Context, scanRoot *scalibrfs.ScanRoot, ix *in Sev: &detector.Severity{Severity: detector.SeverityCritical}, }, Target: &detector.TargetDetails{ - Inventory: inventory, + Package: pkg, }, - Extra: fmt.Sprintf("%s %s %s", inventory.Name, inventory.Version, strings.Join(inventory.Locations, ", ")), + Extra: fmt.Sprintf("%s %s %s", pkg.Name, pkg.Version, strings.Join(pkg.Locations, ", ")), }}, nil } // Find the Ray package and its version -func findRayPackage(ix *inventoryindex.InventoryIndex) (string, *extractor.Inventory) { - inventory := ix.GetSpecific("ray", "pypi") - for _, i := range inventory { - return i.Version, i +func findRayPackage(px *packageindex.PackageIndex) (string, *extractor.Package) { + pkgs := px.GetSpecific("ray", "pypi") + for _, p := range pkgs { + return p.Version, p } return "", nil } diff --git a/detector/cve/cve20242912/cve20242912.go b/detector/cve/cve20242912/cve20242912.go index 6139653a..86b3d63e 100644 --- a/detector/cve/cve20242912/cve20242912.go +++ b/detector/cve/cve20242912/cve20242912.go @@ -37,13 +37,13 @@ import ( "github.com/google/osv-scalibr/extractor" "github.com/google/osv-scalibr/extractor/filesystem/language/python/wheelegg" scalibrfs "github.com/google/osv-scalibr/fs" - "github.com/google/osv-scalibr/inventoryindex" "github.com/google/osv-scalibr/log" + "github.com/google/osv-scalibr/packageindex" "github.com/google/osv-scalibr/plugin" ) type bentomlPackageNames struct { - packageType string + pkgType string name string fixedVersion string } @@ -64,7 +64,7 @@ var ( pickledPayload = []byte("gASVPwAAAAAAAACMBXBvc2l4lIwGc3lzdGVtlJOUjCR0b3VjaCAvdG1wL2JlbnRvbWwtcG9jLUNWRS0yMDI0LTI5MTKUhZRSlC4=") bentomlPackages = []bentomlPackageNames{ { - packageType: "pypi", + pkgType: "pypi", name: "bentoml", fixedVersion: "1.2.5", }, @@ -93,12 +93,12 @@ func (Detector) Requirements() *plugin.Capabilities { // RequiredExtractors returns an empty list as there are no dependencies. func (Detector) RequiredExtractors() []string { return []string{wheelegg.Name} } -func findBentomlVersions(ix *inventoryindex.InventoryIndex) (string, *extractor.Inventory, string) { +func findBentomlVersions(px *packageindex.PackageIndex) (string, *extractor.Package, string) { for _, r := range bentomlPackages { - inventory := ix.GetSpecific(r.name, r.packageType) - if len(inventory) > 0 { - i := inventory[0] - return i.Version, i, r.fixedVersion + pkgs := px.GetSpecific(r.name, r.pkgType) + if len(pkgs) > 0 { + p := pkgs[0] + return p.Version, p, r.fixedVersion } } return "", nil, "" @@ -167,8 +167,8 @@ func fileExists(filesys scalibrfs.FS, path string) bool { } // Scan checks for the presence of the BentoML CVE-2024-2912 vulnerability on the filesystem. -func (d Detector) Scan(ctx context.Context, scanRoot *scalibrfs.ScanRoot, ix *inventoryindex.InventoryIndex) ([]*detector.Finding, error) { - bentomlVersion, inventory, fixedVersion := findBentomlVersions(ix) +func (d Detector) Scan(ctx context.Context, scanRoot *scalibrfs.ScanRoot, px *packageindex.PackageIndex) ([]*detector.Finding, error) { + bentomlVersion, pkg, fixedVersion := findBentomlVersions(px) if bentomlVersion == "" { log.Debugf("No BentoML version found") return nil, nil @@ -236,8 +236,8 @@ func (d Detector) Scan(ctx context.Context, scanRoot *scalibrfs.ScanRoot, ix *in Sev: &detector.Severity{Severity: detector.SeverityCritical}, }, Target: &detector.TargetDetails{ - Inventory: inventory, + Package: pkg, }, - Extra: fmt.Sprintf("%s %s %s", inventory.Name, inventory.Version, strings.Join(inventory.Locations, ", ")), + Extra: fmt.Sprintf("%s %s %s", pkg.Name, pkg.Version, strings.Join(pkg.Locations, ", ")), }}, nil } diff --git a/detector/detector.go b/detector/detector.go index 1f346c66..11d5d59f 100644 --- a/detector/detector.go +++ b/detector/detector.go @@ -23,7 +23,7 @@ import ( "github.com/google/osv-scalibr/extractor" scalibrfs "github.com/google/osv-scalibr/fs" - "github.com/google/osv-scalibr/inventoryindex" + "github.com/google/osv-scalibr/packageindex" "github.com/google/osv-scalibr/plugin" "github.com/google/osv-scalibr/stats" ) @@ -36,9 +36,9 @@ type Detector interface { // Detector to run. RequiredExtractors() []string // Scan performs the security scan, considering scanRoot to be the root directory. - // Implementations may use InventoryIndex to check if a relevant software package is installed and + // Implementations may use PackageIndex to check if a relevant software package is installed and // terminate early if it's not. - Scan(c context.Context, scanRoot *scalibrfs.ScanRoot, ix *inventoryindex.InventoryIndex) ([]*Finding, error) + Scan(c context.Context, scanRoot *scalibrfs.ScanRoot, px *packageindex.PackageIndex) ([]*Finding, error) } // LINT.IfChange @@ -123,9 +123,9 @@ const ( // TargetDetails contains instance-specific details about the security finding. type TargetDetails struct { - // The software affected by the finding. Taken from the Inventory extraction results. - Inventory *extractor.Inventory - // Location of vulnerable files not related to the inventory, + // The software affected by the finding. Taken from the Package extraction results. + Package *extractor.Package + // Location of vulnerable files not related to the package, // e.g. config files with misconfigurations. Location []string } @@ -134,7 +134,7 @@ type TargetDetails struct { // Run runs the specified detectors and returns their findings, // as well as info about whether the plugin runs completed successfully. -func Run(ctx context.Context, c stats.Collector, detectors []Detector, scanRoot *scalibrfs.ScanRoot, index *inventoryindex.InventoryIndex) ([]*Finding, []*plugin.Status, error) { +func Run(ctx context.Context, c stats.Collector, detectors []Detector, scanRoot *scalibrfs.ScanRoot, index *packageindex.PackageIndex) ([]*Finding, []*plugin.Status, error) { findings := []*Finding{} status := []*plugin.Status{} for _, d := range detectors { diff --git a/detector/detector_test.go b/detector/detector_test.go index f4d5afd6..87c46af0 100644 --- a/detector/detector_test.go +++ b/detector/detector_test.go @@ -24,7 +24,7 @@ import ( "github.com/google/osv-scalibr/detector" "github.com/google/osv-scalibr/extractor" scalibrfs "github.com/google/osv-scalibr/fs" - "github.com/google/osv-scalibr/inventoryindex" + "github.com/google/osv-scalibr/packageindex" "github.com/google/osv-scalibr/plugin" "github.com/google/osv-scalibr/stats" fd "github.com/google/osv-scalibr/testing/fakedetector" @@ -150,10 +150,10 @@ func TestRun(t *testing.T) { for _, tc := range testCases { t.Run(tc.desc, func(t *testing.T) { - ix, _ := inventoryindex.New([]*extractor.Inventory{}) + px, _ := packageindex.New([]*extractor.Package{}) tmp := t.TempDir() gotFindings, gotStatus, err := detector.Run( - context.Background(), stats.NoopCollector{}, tc.det, scalibrfs.RealFSScanRoot(tmp), ix, + context.Background(), stats.NoopCollector{}, tc.det, scalibrfs.RealFSScanRoot(tmp), px, ) if diff := cmp.Diff(tc.wantErr, err, cmpopts.EquateErrors()); diff != "" { t.Errorf("detector.Run(%v): unexpected error (-want +got):\n%s", tc.det, diff) diff --git a/detector/govulncheck/binary/binary.go b/detector/govulncheck/binary/binary.go index 5ecbf6e8..1cce6387 100644 --- a/detector/govulncheck/binary/binary.go +++ b/detector/govulncheck/binary/binary.go @@ -27,8 +27,8 @@ import ( "github.com/google/osv-scalibr/detector" "github.com/google/osv-scalibr/extractor/filesystem/language/golang/gobinary" scalibrfs "github.com/google/osv-scalibr/fs" - "github.com/google/osv-scalibr/inventoryindex" "github.com/google/osv-scalibr/log" + "github.com/google/osv-scalibr/packageindex" "github.com/google/osv-scalibr/plugin" "github.com/google/osv-scalibr/purl" "golang.org/x/vuln/scan" @@ -71,16 +71,16 @@ func (Detector) RequiredExtractors() []string { } // Scan takes the go binaries gathered in the extraction phase and runs govulncheck on them. -func (d Detector) Scan(ctx context.Context, scanRoot *scalibrfs.ScanRoot, ix *inventoryindex.InventoryIndex) ([]*detector.Finding, error) { +func (d Detector) Scan(ctx context.Context, scanRoot *scalibrfs.ScanRoot, px *packageindex.PackageIndex) ([]*detector.Finding, error) { result := []*detector.Finding{} scanned := make(map[string]bool) var allErrs error = nil - for _, i := range ix.GetAllOfType(purl.TypeGolang) { + for _, p := range px.GetAllOfType(purl.TypeGolang) { // We only look at Go binaries (no source code). - if i.Extractor.Name() != gobinary.Name { + if p.Extractor.Name() != gobinary.Name { continue } - for _, l := range i.Locations { + for _, l := range p.Locations { if scanned[l] { continue } diff --git a/detector/govulncheck/binary/binary_test.go b/detector/govulncheck/binary/binary_test.go index 6f3a5e08..8f74882e 100644 --- a/detector/govulncheck/binary/binary_test.go +++ b/detector/govulncheck/binary/binary_test.go @@ -29,7 +29,7 @@ import ( "github.com/google/osv-scalibr/extractor" "github.com/google/osv-scalibr/extractor/filesystem/language/golang/gobinary" scalibrfs "github.com/google/osv-scalibr/fs" - "github.com/google/osv-scalibr/inventoryindex" + "github.com/google/osv-scalibr/packageindex" ) const binaryName = "semaphore-demo-go" @@ -46,17 +46,17 @@ func TestScan(t *testing.T) { det := binary.Detector{ OfflineVulnDBPath: filepath.ToSlash(filepath.Join(wd, "testdata", "vulndb")), } - ix := setupInventoryIndex([]string{binaryName}) - findings, err := det.Scan(context.Background(), scalibrfs.RealFSScanRoot("."), ix) + px := setupPackageIndex([]string{binaryName}) + findings, err := det.Scan(context.Background(), scalibrfs.RealFSScanRoot("."), px) if err != nil { - t.Fatalf("detector.Scan(%v): %v", ix, err) + t.Fatalf("detector.Scan(%v): %v", px, err) } // There are two vulns in the test vulndb defined for two // module dependencies of the test binary. Both dependencies // are used at a vulnerable version. However, for only one // there is a vulnerable symbol present in the binary. if len(findings) != 1 { - t.Fatalf("detector.Scan(%v): expected 1 finding, got: %v", ix, findings) + t.Fatalf("detector.Scan(%v): expected 1 finding, got: %v", px, findings) } got := findings[0] wantTitle := "Excessive memory growth in net/http and golang.org/x/net/http2" @@ -83,12 +83,12 @@ func TestScan(t *testing.T) { Extra: got.Extra, } if diff := cmp.Diff(want, got); diff != "" { - t.Errorf("detector.Scan(%v): unexpected findings (-want +got):\n%s", ix, diff) + t.Errorf("detector.Scan(%v): unexpected findings (-want +got):\n%s", px, diff) } // We only check the prefix of the extra info as the specific info surfaced might // change between govulncheck versions. if !strings.HasPrefix(got.Extra, wantExtraPrefix) { - t.Errorf("detector.Scan(%v): unexpected extra. Want prefix %q, got %q", ix, wantExtraPrefix, got.Extra) + t.Errorf("detector.Scan(%v): unexpected extra. Want prefix %q, got %q", px, wantExtraPrefix, got.Extra) } } @@ -104,26 +104,26 @@ func TestScanErrorInGovulncheck(t *testing.T) { det := binary.Detector{ OfflineVulnDBPath: filepath.ToSlash(filepath.Join(wd, "testdata", "vulndb")), } - ix := setupInventoryIndex([]string{"nonexistent", binaryName}) - result, err := det.Scan(context.Background(), scalibrfs.RealFSScanRoot("."), ix) + px := setupPackageIndex([]string{"nonexistent", binaryName}) + result, err := det.Scan(context.Background(), scalibrfs.RealFSScanRoot("."), px) if err == nil { - t.Fatalf("detector.Scan(%v): Expected an error, got none", ix) + t.Fatalf("detector.Scan(%v): Expected an error, got none", px) } if len(result) == 0 { - t.Fatalf("detector.Scan(%v): Expected scan results, got none", ix) + t.Fatalf("detector.Scan(%v): Expected scan results, got none", px) } } -func setupInventoryIndex(names []string) *inventoryindex.InventoryIndex { - invs := []*extractor.Inventory{} +func setupPackageIndex(names []string) *packageindex.PackageIndex { + pkgs := []*extractor.Package{} for _, n := range names { - invs = append(invs, &extractor.Inventory{ + pkgs = append(pkgs, &extractor.Package{ Name: n, Version: "1.2.3", Locations: []string{filepath.Join("testdata", n)}, Extractor: &gobinary.Extractor{}, }) } - ix, _ := inventoryindex.New(invs) - return ix + px, _ := packageindex.New(pkgs) + return px } diff --git a/detector/weakcredentials/etcshadow/etcshadow.go b/detector/weakcredentials/etcshadow/etcshadow.go index f0142586..0aec9ee2 100644 --- a/detector/weakcredentials/etcshadow/etcshadow.go +++ b/detector/weakcredentials/etcshadow/etcshadow.go @@ -27,7 +27,7 @@ import ( "github.com/google/osv-scalibr/detector" scalibrfs "github.com/google/osv-scalibr/fs" - "github.com/google/osv-scalibr/inventoryindex" + "github.com/google/osv-scalibr/packageindex" "github.com/google/osv-scalibr/plugin" ) @@ -57,7 +57,7 @@ func (Detector) Requirements() *plugin.Capabilities { return &plugin.Capabilitie func (Detector) RequiredExtractors() []string { return []string{} } // Scan starts the scan. -func (d Detector) Scan(ctx context.Context, scanRoot *scalibrfs.ScanRoot, ix *inventoryindex.InventoryIndex) ([]*detector.Finding, error) { +func (d Detector) Scan(ctx context.Context, scanRoot *scalibrfs.ScanRoot, px *packageindex.PackageIndex) ([]*detector.Finding, error) { f, err := scanRoot.FS.Open("etc/shadow") if err != nil { if errors.Is(err, os.ErrNotExist) { diff --git a/detector/weakcredentials/etcshadow/etcshadow_test.go b/detector/weakcredentials/etcshadow/etcshadow_test.go index 45269d92..9b8da58c 100644 --- a/detector/weakcredentials/etcshadow/etcshadow_test.go +++ b/detector/weakcredentials/etcshadow/etcshadow_test.go @@ -28,7 +28,7 @@ import ( "github.com/google/osv-scalibr/detector/weakcredentials/etcshadow" "github.com/google/osv-scalibr/extractor" scalibrfs "github.com/google/osv-scalibr/fs" - "github.com/google/osv-scalibr/inventoryindex" + "github.com/google/osv-scalibr/packageindex" ) // All users have the password "Password123" using distinct hashing algorithms. @@ -108,7 +108,7 @@ func TestScan(t *testing.T) { Sev: &detector.Severity{Severity: detector.SeverityCritical}, } - ix, _ := inventoryindex.New([]*extractor.Inventory{}) + px, _ := packageindex.New([]*extractor.Package{}) testCases := []struct { desc string fsys scalibrfs.FS @@ -146,7 +146,7 @@ func TestScan(t *testing.T) { for _, tc := range testCases { t.Run(tc.desc, func(t *testing.T) { detector := etcshadow.Detector{} - findings, err := detector.Scan(context.Background(), &scalibrfs.ScanRoot{FS: tc.fsys}, ix) + findings, err := detector.Scan(context.Background(), &scalibrfs.ScanRoot{FS: tc.fsys}, px) if diff := cmp.Diff(tc.wantErr, err, cmpopts.EquateErrors()); diff != "" { t.Fatalf("detector.Scan(%v): unexpected error (-want +got):\n%s", tc.fsys, diff) } @@ -160,12 +160,12 @@ func TestScan(t *testing.T) { } func TestScanCancelled(t *testing.T) { - ix, _ := inventoryindex.New([]*extractor.Inventory{}) + px, _ := packageindex.New([]*extractor.Package{}) detector := etcshadow.Detector{} fsys := &fakeFS{files: map[string]string{"etc/shadow": sampleEtcShadow}} ctx, cancelFunc := context.WithCancel(context.Background()) cancelFunc() - findings, err := detector.Scan(ctx, &scalibrfs.ScanRoot{FS: fsys}, ix) + findings, err := detector.Scan(ctx, &scalibrfs.ScanRoot{FS: fsys}, px) if findings != nil || err != ctx.Err() { t.Errorf("expected scan to be cancelled") } diff --git a/detector/weakcredentials/filebrowser/filebrowser.go b/detector/weakcredentials/filebrowser/filebrowser.go index 811a1a52..5b3a1b70 100644 --- a/detector/weakcredentials/filebrowser/filebrowser.go +++ b/detector/weakcredentials/filebrowser/filebrowser.go @@ -31,8 +31,8 @@ import ( "github.com/google/osv-scalibr/detector" scalibrfs "github.com/google/osv-scalibr/fs" - "github.com/google/osv-scalibr/inventoryindex" "github.com/google/osv-scalibr/log" + "github.com/google/osv-scalibr/packageindex" "github.com/google/osv-scalibr/plugin" ) @@ -86,7 +86,7 @@ func (Detector) Requirements() *plugin.Capabilities { func (Detector) RequiredExtractors() []string { return []string{} } // Scan starts the scan. -func (d Detector) Scan(ctx context.Context, scanRoot *scalibrfs.ScanRoot, ix *inventoryindex.InventoryIndex) ([]*detector.Finding, error) { +func (d Detector) Scan(ctx context.Context, scanRoot *scalibrfs.ScanRoot, px *packageindex.PackageIndex) ([]*detector.Finding, error) { for _, fileBrowserPort := range fileBrowserPorts { if ctx.Err() != nil { return nil, ctx.Err() diff --git a/detector/weakcredentials/winlocal/winlocal_dummy.go b/detector/weakcredentials/winlocal/winlocal_dummy.go index 26d35660..0665f41b 100644 --- a/detector/weakcredentials/winlocal/winlocal_dummy.go +++ b/detector/weakcredentials/winlocal/winlocal_dummy.go @@ -22,7 +22,7 @@ import ( "github.com/google/osv-scalibr/detector" scalibrfs "github.com/google/osv-scalibr/fs" - "github.com/google/osv-scalibr/inventoryindex" + "github.com/google/osv-scalibr/packageindex" "github.com/google/osv-scalibr/plugin" ) @@ -54,6 +54,6 @@ func (Detector) Requirements() *plugin.Capabilities { func (Detector) RequiredExtractors() []string { return nil } // Scan starts the scan. -func (d Detector) Scan(ctx context.Context, scanRoot *scalibrfs.ScanRoot, ix *inventoryindex.InventoryIndex) ([]*detector.Finding, error) { +func (d Detector) Scan(ctx context.Context, scanRoot *scalibrfs.ScanRoot, px *packageindex.PackageIndex) ([]*detector.Finding, error) { return nil, fmt.Errorf("only supported on Windows") } diff --git a/detector/weakcredentials/winlocal/winlocal_windows.go b/detector/weakcredentials/winlocal/winlocal_windows.go index 99253197..231b5c22 100644 --- a/detector/weakcredentials/winlocal/winlocal_windows.go +++ b/detector/weakcredentials/winlocal/winlocal_windows.go @@ -31,7 +31,7 @@ import ( "github.com/google/osv-scalibr/detector/weakcredentials/winlocal/samreg" "github.com/google/osv-scalibr/detector/weakcredentials/winlocal/systemreg" scalibrfs "github.com/google/osv-scalibr/fs" - "github.com/google/osv-scalibr/inventoryindex" + "github.com/google/osv-scalibr/packageindex" "github.com/google/osv-scalibr/plugin" "golang.org/x/sys/windows/registry" ) @@ -86,7 +86,7 @@ func (Detector) Requirements() *plugin.Capabilities { func (Detector) RequiredExtractors() []string { return nil } // Scan starts the scan. -func (d Detector) Scan(ctx context.Context, _ *scalibrfs.ScanRoot, _ *inventoryindex.InventoryIndex) ([]*detector.Finding, error) { +func (d Detector) Scan(ctx context.Context, _ *scalibrfs.ScanRoot, _ *packageindex.PackageIndex) ([]*detector.Finding, error) { hashes, err := d.hashes(ctx) if err != nil || len(hashes) == 0 { return nil, err diff --git a/docs/new_detector.md b/docs/new_detector.md index 9e3f30d6..fdb1dc16 100644 --- a/docs/new_detector.md +++ b/docs/new_detector.md @@ -59,7 +59,7 @@ place it in there. Otherwise, feel free to create a new directory. ## Scan parameters -Detectors can access the filesystem and the results of the inventory extraction +Detectors can access the filesystem and the results of the package extraction step through the parameters of their `Scan()` function. ### Filesystem access @@ -69,11 +69,11 @@ allows them to read the contents and permissions of any file on the scanned filesystem. Note that the access is read-only: Detectors are not able to make changes to the target machine. -### Inventory index +### Package index -Detectors also receive an -[`InventoryIndex`](/inventoryindex/inventory_index.go) -param that can be used to query the software inventory that the extraction step +Detectors also receive a +[`PackageIndex`](/packageindex/package_index.go) +param that can be used to query the software package that the extraction step found on the filesystem. This can be used to run the detection logic on each relevant software found, or exit early if none are installed. For an example use case see the [govulncheck Detector](/detector/govulncheck/binary/binary.go). diff --git a/docs/new_extractor.md b/docs/new_extractor.md index d4468ff0..c54b819f 100644 --- a/docs/new_extractor.md +++ b/docs/new_extractor.md @@ -1,7 +1,7 @@ # Add a new Extractor -Extractors are plugins that extract a inventory information, represented by the -Inventory struct. They are called on every file of system (filesystem +Extractors are plugins that extract inventory information, represented by the +Package struct. They are called on every file of system (filesystem extractor). There should be one Extractor per parsing logic. In python for example there are @@ -69,12 +69,12 @@ which contains the path, `fs.FileInfo` and `io.Reader` for the file. ## Output The `Extract` method should return a list of -[Inventory](https://github.com/google/osv-scalibr/blob/28397d99/extractor/extractor.go#L44). +[Package](https://github.com/google/osv-scalibr/blob/28397d99/extractor/extractor.go#L44). - + -You can return an empty list in case you don't find inventory in the file or -multiple Inventory entries in case there are multiple in one file. +You can return an empty list in case you don't find software packages in the +file or multiple Package entries in case there are multiple in one file. ## Code location @@ -120,7 +120,7 @@ extractor as an example. 1. Implement `FileRequired` to return true in case filename and fileMode matches a file you need to parse. For example, the JavaScript `package.json` extractor returns true for any file named `package.json`. -1. Implement `Extract` to extract inventory inside the file. +1. Implement `Extract` to extract software packages inside the file. 1. If you introduced any new metadata type, be sure to add them to the scan_results.proto as well and re-generate the go_proto: @@ -134,7 +134,7 @@ extractor as an example. $ `go mod tidy` ``` -1. Implement `ToPURL` to generate PURLs from the Inventory +1. Implement `ToPURL` to generate PURLs from the Package extracted. If your extractor doesn't support CPEs feel free to return an empty list. 1. Write tests (you can separate tests for FileRequired and Extract, to avoid diff --git a/extractor/extractor.go b/extractor/extractor.go index 49136c7d..c7afd175 100644 --- a/extractor/extractor.go +++ b/extractor/extractor.go @@ -23,11 +23,11 @@ import ( // Extractor is the common interface of inventory extraction plugins. type Extractor interface { plugin.Plugin - // ToPURL converts an inventory created by this extractor into a PURL. - ToPURL(i *Inventory) *purl.PackageURL - // Ecosystem returns the Ecosystem of the given inventory created by this extractor. + // ToPURL converts a package created by this extractor into a PURL. + ToPURL(p *Package) *purl.PackageURL + // Ecosystem returns the Ecosystem of the given package created by this extractor. // For software packages this corresponds to an OSV ecosystem value, e.g. PyPI. - Ecosystem(i *Inventory) string + Ecosystem(p *Package) string } // LINT.IfChange @@ -46,8 +46,10 @@ type LayerDetails struct { InBaseImage bool } -// Inventory is an instance of a software package or library found by the extractor. -type Inventory struct { +// Package is an instance of a software package or library found by the extractor. +// TODO(b/400910349): Currently package is also used to store non-package data like open ports. +// Move these into their own dedicated types. +type Package struct { // A human-readable name representation of the package. Note that this field // should only be used for things like logging as different packages can have // multiple different types of names (e.g. .deb packages have a source name @@ -71,7 +73,7 @@ type Inventory struct { Metadata any } -// Annotation are additional information about the inventory. +// Annotation are additional information about the package. type Annotation int64 const ( @@ -88,10 +90,10 @@ const ( InsideCacheDir ) -// Ecosystem returns the Ecosystem of the inventory. For software packages this corresponds +// Ecosystem returns the Ecosystem of the package. For software packages this corresponds // to an OSV ecosystem value, e.g. PyPI. -func (i *Inventory) Ecosystem() string { - return i.Extractor.Ecosystem(i) +func (p *Package) Ecosystem() string { + return p.Extractor.Ecosystem(p) } // LINT.ThenChange(/binary/proto/scan_result.proto) diff --git a/extractor/filesystem/containers/containerd/containerd_dummy.go b/extractor/filesystem/containers/containerd/containerd_dummy.go index 0308a186..94ec98df 100644 --- a/extractor/filesystem/containers/containerd/containerd_dummy.go +++ b/extractor/filesystem/containers/containerd/containerd_dummy.go @@ -65,12 +65,12 @@ func (e Extractor) FileRequired(_ filesystem.FileAPI) bool { } // Extract not implemented. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { return nil, fmt.Errorf("not supported") } // ToPURL not implemented. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { return nil } +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { return nil } // Ecosystem not defined. -func (Extractor) Ecosystem(i *extractor.Inventory) string { return "" } +func (Extractor) Ecosystem(p *extractor.Package) string { return "" } diff --git a/extractor/filesystem/containers/containerd/containerd_linux.go b/extractor/filesystem/containers/containerd/containerd_linux.go index 960a62a8..41c3e164 100644 --- a/extractor/filesystem/containers/containerd/containerd_linux.go +++ b/extractor/filesystem/containers/containerd/containerd_linux.go @@ -14,7 +14,7 @@ //go:build linux -// Package containerd extracts container inventory from containerd metadb database. +// Package containerd extracts container package from containerd metadb database. package containerd import ( @@ -80,7 +80,7 @@ type Extractor struct { maxMetaDBFileSize int64 } -// New returns a containerd container inventory extractor. +// New returns a containerd container package extractor. func New(cfg Config) *Extractor { return &Extractor{ maxMetaDBFileSize: cfg.MaxMetaDBFileSize, @@ -122,18 +122,18 @@ func (e Extractor) FileRequired(api filesystem.FileAPI) bool { } } -// Extract container inventory through the containerd metadb file passed as the scan input. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { - var inventory = []*extractor.Inventory{} +// Extract container package through the containerd metadb file passed as the scan input. +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { + var pkgs = []*extractor.Package{} if input.Info != nil && input.Info.Size() > e.maxMetaDBFileSize { - return inventory, fmt.Errorf("Containerd metadb file %s is too large: %d", input.Path, input.Info.Size()) + return pkgs, fmt.Errorf("Containerd metadb file %s is too large: %d", input.Path, input.Info.Size()) } // Timeout is added to make sure Scalibr does not hand if the metadb file is open by another process. // This will still allow to handle the snapshot of a machine. metaDB, err := bolt.Open(filepath.Join(input.Root, input.Path), 0444, &bolt.Options{Timeout: 1 * time.Second}) if err != nil { - return inventory, fmt.Errorf("Could not read the containerd metadb file: %v", err) + return pkgs, fmt.Errorf("Could not read the containerd metadb file: %v", err) } defer metaDB.Close() @@ -144,26 +144,26 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] fullMetadataDBPath := filepath.Join(input.Root, snapshotterMetadataDBPath) snapshotsMetadata, err = snapshotsMetadataFromDB(fullMetadataDBPath, e.maxMetaDBFileSize, "overlayfs") if err != nil { - return inventory, fmt.Errorf("Could not collect snapshots metadata from DB: %v", err) + return pkgs, fmt.Errorf("Could not collect snapshots metadata from DB: %v", err) } } ctrMetadata, err := containersFromMetaDB(ctx, metaDB, input.Root, snapshotsMetadata) if err != nil { - log.Errorf("Could not get container inventory from the containerd metadb file: %v", err) - return inventory, err + log.Errorf("Could not get container package from the containerd metadb file: %v", err) + return pkgs, err } for _, ctr := range ctrMetadata { - pkg := &extractor.Inventory{ + pkg := &extractor.Package{ Name: ctr.ImageName, Version: ctr.ImageDigest, Locations: []string{input.Path}, Metadata: &ctr, } - inventory = append(inventory, pkg) + pkgs = append(pkgs, pkg) } - return inventory, nil + return pkgs, nil } // This method checks if the given file is valid to be opened, and make sure it's not oversized. @@ -490,8 +490,8 @@ func runhcsInitPid(scanRoot string, runtimeName string, namespace string, id str return initPID } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { return nil } +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { return nil } -// Ecosystem returns no ecosystem since the Inventory is not a software package. -func (Extractor) Ecosystem(i *extractor.Inventory) string { return "" } +// Ecosystem returns no ecosystem since the Package is not a software package. +func (Extractor) Ecosystem(p *extractor.Package) string { return "" } diff --git a/extractor/filesystem/containers/containerd/containerd_test.go b/extractor/filesystem/containers/containerd/containerd_test.go index 45e9d22e..2510e7c8 100644 --- a/extractor/filesystem/containers/containerd/containerd_test.go +++ b/extractor/filesystem/containers/containerd/containerd_test.go @@ -91,7 +91,7 @@ func TestExtract(t *testing.T) { containerdID string cfg containerd.Config onGoos string - wantInventory []*extractor.Inventory + wantPackages []*extractor.Package wantErr error }{ { @@ -105,7 +105,7 @@ func TestExtract(t *testing.T) { MaxMetaDBFileSize: 500 * units.MiB, }, onGoos: "linux", - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "602401143452.dkr.ecr.us-west-2.amazonaws.com/eks/eks-pod-identity-agent:0.1.15", Version: "sha256:832ad48c9872fdcae32f2ea369d9874fa34f2ea369d9874fa34f271b4dbc58ce04393c757befa462", @@ -137,8 +137,8 @@ func TestExtract(t *testing.T) { cfg: containerd.Config{ MaxMetaDBFileSize: 500 * units.MiB, }, - wantInventory: []*extractor.Inventory{}, - wantErr: cmpopts.AnyError, + wantPackages: []*extractor.Package{}, + wantErr: cmpopts.AnyError, }, { name: "metadb too large", @@ -151,8 +151,8 @@ func TestExtract(t *testing.T) { cfg: containerd.Config{ MaxMetaDBFileSize: 1 * units.KiB, }, - wantInventory: []*extractor.Inventory{}, - wantErr: cmpopts.AnyError, + wantPackages: []*extractor.Package{}, + wantErr: cmpopts.AnyError, }, { name: "invalid status file", @@ -165,7 +165,7 @@ func TestExtract(t *testing.T) { cfg: containerd.Config{ MaxMetaDBFileSize: 500 * units.MiB, }, - wantInventory: []*extractor.Inventory{}, + wantPackages: []*extractor.Package{}, }, { name: "metadb valid windows", @@ -178,7 +178,7 @@ func TestExtract(t *testing.T) { }, // TODO(b/350963790): Enable this test case once the extractor is supported on Windows. onGoos: "ignore", - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "mcr.microsoft.com/windows/nanoserver:ltsc2022", Version: "sha256:31c8aa02d47af7d65c11da9c3a279c8407c32afd3fc6bec2e9a544db8e3715b3", @@ -205,7 +205,7 @@ func TestExtract(t *testing.T) { cfg: containerd.Config{ MaxMetaDBFileSize: 500 * units.MiB, }, - wantInventory: []*extractor.Inventory{}, + wantPackages: []*extractor.Package{}, }, } @@ -238,7 +238,7 @@ func TestExtract(t *testing.T) { ignoreOrder := cmpopts.SortSlices(func(a, b any) bool { return fmt.Sprintf("%+v", a) < fmt.Sprintf("%+v", b) }) - if diff := cmp.Diff(tt.wantInventory, got, ignoreOrder); diff != "" { + if diff := cmp.Diff(tt.wantPackages, got, ignoreOrder); diff != "" { t.Errorf("Extract(%s) (-want +got):\n%s", tt.path, diff) } }) diff --git a/extractor/filesystem/filesystem.go b/extractor/filesystem/filesystem.go index ab3e7c99..82550875 100644 --- a/extractor/filesystem/filesystem.go +++ b/extractor/filesystem/filesystem.go @@ -52,7 +52,7 @@ type Extractor interface { // library for that. FileRequired(api FileAPI) bool // Extract extracts inventory data relevant for the extractor from a given file. - Extract(ctx context.Context, input *ScanInput) ([]*extractor.Inventory, error) + Extract(ctx context.Context, input *ScanInput) ([]*extractor.Package, error) } // FileAPI is the interface for accessing file information and path. @@ -100,7 +100,7 @@ type Config struct { ReadSymlinks bool // Optional: Limit for visited inodes. If 0, no limit is applied. MaxInodes int - // Optional: By default, inventories stores a path relative to the scan root. If StoreAbsolutePath + // Optional: By default, inventory paths are relative to the scan root. If StoreAbsolutePath // is set, the absolute path is stored instead. StoreAbsolutePath bool // Optional: If true, print a detailed analysis of the duration of each extractor. @@ -111,9 +111,9 @@ type Config struct { // Run runs the specified extractors and returns their extraction results, // as well as info about whether the plugin runs completed successfully. -func Run(ctx context.Context, config *Config) ([]*extractor.Inventory, []*plugin.Status, error) { +func Run(ctx context.Context, config *Config) ([]*extractor.Package, []*plugin.Status, error) { if len(config.Extractors) == 0 { - return []*extractor.Inventory{}, []*plugin.Status{}, nil + return []*extractor.Package{}, []*plugin.Status{}, nil } scanRoots, err := expandAllAbsolutePaths(config.ScanRoots) @@ -126,23 +126,23 @@ func Run(ctx context.Context, config *Config) ([]*extractor.Inventory, []*plugin return nil, nil, err } - var inventory []*extractor.Inventory + var pkgs []*extractor.Package var status []*plugin.Status for _, root := range scanRoots { - inv, st, err := runOnScanRoot(ctx, config, root, wc) + pkg, st, err := runOnScanRoot(ctx, config, root, wc) if err != nil { return nil, nil, err } - inventory = append(inventory, inv...) + pkgs = append(pkgs, pkg...) status = append(status, st...) } - return inventory, status, nil + return pkgs, status, nil } -func runOnScanRoot(ctx context.Context, config *Config, scanRoot *scalibrfs.ScanRoot, wc *walkContext) ([]*extractor.Inventory, []*plugin.Status, error) { +func runOnScanRoot(ctx context.Context, config *Config, scanRoot *scalibrfs.ScanRoot, wc *walkContext) ([]*extractor.Package, []*plugin.Status, error) { abs := "" var err error if !scanRoot.IsVirtual() { @@ -187,9 +187,9 @@ func InitWalkContext(ctx context.Context, config *Config, absScanRoots []*scalib lastStatus: time.Now(), - inventory: []*extractor.Inventory{}, + pkgs: []*extractor.Package{}, errors: make(map[string]error), - foundInv: make(map[string]bool), + foundPKGs: make(map[string]bool), fileAPI: &lazyFileAPI{}, }, nil @@ -199,7 +199,7 @@ func InitWalkContext(ctx context.Context, config *Config, absScanRoots []*scalib // as well as info about whether the plugin runs completed successfully. // scanRoot is the location of fsys. // This method is for testing, use Run() to avoid confusion with scanRoot vs fsys. -func RunFS(ctx context.Context, config *Config, wc *walkContext) ([]*extractor.Inventory, []*plugin.Status, error) { +func RunFS(ctx context.Context, config *Config, wc *walkContext) ([]*extractor.Package, []*plugin.Status, error) { start := time.Now() if wc == nil || wc.fs == nil { return nil, nil, fmt.Errorf("walk context is nil") @@ -234,7 +234,7 @@ func RunFS(ctx context.Context, config *Config, wc *walkContext) ([]*extractor.I log.Infof("End status: %d dirs visited, %d inodes visited, %d Extract calls, %s elapsed, %s wall time", wc.dirsVisited, wc.inodesVisited, wc.extractCalls, time.Since(start), time.Duration(time.Now().UnixNano()-start.UnixNano())) - return wc.inventory, errToExtractorStatus(config.Extractors, wc.foundInv, wc.errors), err + return wc.pkgs, errToExtractorStatus(config.Extractors, wc.foundPKGs, wc.errors), err } type walkContext struct { @@ -254,12 +254,12 @@ type walkContext struct { storeAbsolutePath bool errorOnFSErrors bool - // Inventories found. - inventory []*extractor.Inventory + // Packages found. + pkgs []*extractor.Package // Extractor name to runtime errors. errors map[string]error - // Whether an extractor found any inventory. - foundInv map[string]bool + // Whether an extractor found any packages. + foundPKGs map[string]bool // Whether to read symlinks. readSymlinks bool @@ -406,13 +406,13 @@ func (wc *walkContext) runExtractor(ex Extractor, path string) { } if len(results) > 0 { - wc.foundInv[ex.Name()] = true + wc.foundPKGs[ex.Name()] = true for _, r := range results { r.Extractor = ex if wc.storeAbsolutePath { r.Locations = expandAbsolutePath(wc.scanRoot, r.Locations) } - wc.inventory = append(wc.inventory, r) + wc.pkgs = append(wc.pkgs, r) } } } @@ -504,10 +504,10 @@ func addErrToMap(errors map[string]error, key string, err error) { } } -func errToExtractorStatus(extractors []Extractor, foundInv map[string]bool, errors map[string]error) []*plugin.Status { +func errToExtractorStatus(extractors []Extractor, foundPKGs map[string]bool, errors map[string]error) []*plugin.Status { result := make([]*plugin.Status, 0, len(extractors)) for _, ex := range extractors { - result = append(result, plugin.StatusFromErr(ex, foundInv[ex.Name()], errors[ex.Name()])) + result = append(result, plugin.StatusFromErr(ex, foundPKGs[ex.Name()], errors[ex.Name()])) } return result } diff --git a/extractor/filesystem/filesystem_test.go b/extractor/filesystem/filesystem_test.go index b93b691b..3ab78866 100644 --- a/extractor/filesystem/filesystem_test.go +++ b/extractor/filesystem/filesystem_test.go @@ -170,7 +170,7 @@ func TestRunFS(t *testing.T) { fakeEx1 := fe.New("ex1", 1, []string{path1}, map[string]fe.NamesErr{path1: {Names: []string{name1}, Err: nil}}) fakeEx2 := fe.New("ex2", 2, []string{path2}, map[string]fe.NamesErr{path2: {Names: []string{name2}, Err: nil}}) - fakeEx2WithInv1 := fe.New("ex2", 2, []string{path2}, map[string]fe.NamesErr{path2: {Names: []string{name1}, Err: nil}}) + fakeEx2WithPKG1 := fe.New("ex2", 2, []string{path2}, map[string]fe.NamesErr{path2: {Names: []string{name1}, Err: nil}}) fakeExWithPartialResult := fe.New("ex1", 1, []string{path1}, map[string]fe.NamesErr{path1: {Names: []string{name1}, Err: errors.New("extraction failed")}}) cwd, err := os.Getwd() @@ -188,14 +188,14 @@ func TestRunFS(t *testing.T) { storeAbsPath bool maxInodes int wantErr error - wantInv []*extractor.Inventory + wantPKGs []*extractor.Package wantStatus []*plugin.Status wantInodeCount int }{ { desc: "Extractors successful", ex: []filesystem.Extractor{fakeEx1, fakeEx2}, - wantInv: []*extractor.Inventory{ + wantPKGs: []*extractor.Package{ { Name: name1, Locations: []string{path1}, @@ -218,7 +218,7 @@ func TestRunFS(t *testing.T) { ex: []filesystem.Extractor{fakeEx1, fakeEx2}, // ScanRoot is CWD dirsToSkip: []string{path.Join(cwd, "dir1")}, - wantInv: []*extractor.Inventory{ + wantPKGs: []*extractor.Package{ { Name: name2, Locations: []string{path2}, @@ -235,7 +235,7 @@ func TestRunFS(t *testing.T) { desc: "Dir skipped with absolute path", ex: []filesystem.Extractor{fakeEx1, fakeEx2}, dirsToSkip: []string{"dir1"}, - wantInv: []*extractor.Inventory{ + wantPKGs: []*extractor.Package{ { Name: name2, Locations: []string{path2}, @@ -252,7 +252,7 @@ func TestRunFS(t *testing.T) { desc: "Dir skipped using regex", ex: []filesystem.Extractor{fakeEx1, fakeEx2}, skipDirRegex: ".*1", - wantInv: []*extractor.Inventory{ + wantPKGs: []*extractor.Package{ { Name: name2, Locations: []string{path2}, @@ -269,7 +269,7 @@ func TestRunFS(t *testing.T) { desc: "Dir skipped with full match of dirname", ex: []filesystem.Extractor{fakeEx1, fakeEx2}, skipDirRegex: "/sub$", - wantInv: []*extractor.Inventory{ + wantPKGs: []*extractor.Package{ { Name: name1, Locations: []string{path1}, @@ -286,7 +286,7 @@ func TestRunFS(t *testing.T) { desc: "skip regex set but not match", ex: []filesystem.Extractor{fakeEx1, fakeEx2}, skipDirRegex: "asdf", - wantInv: []*extractor.Inventory{ + wantPKGs: []*extractor.Package{ { Name: name1, Locations: []string{path1}, @@ -308,7 +308,7 @@ func TestRunFS(t *testing.T) { desc: "Dirs skipped using glob", ex: []filesystem.Extractor{fakeEx1, fakeEx2}, skipDirGlob: "dir*", - wantInv: []*extractor.Inventory{}, + wantPKGs: []*extractor.Package{}, wantStatus: []*plugin.Status{ {Name: "ex1", Version: 1, Status: success}, {Name: "ex2", Version: 2, Status: success}, @@ -319,7 +319,7 @@ func TestRunFS(t *testing.T) { desc: "Subdirectory skipped using glob", ex: []filesystem.Extractor{fakeEx1, fakeEx2}, skipDirGlob: "**/sub", - wantInv: []*extractor.Inventory{ + wantPKGs: []*extractor.Package{ { Name: name1, Locations: []string{path1}, @@ -336,7 +336,7 @@ func TestRunFS(t *testing.T) { desc: "Dirs skipped using glob pattern lists", ex: []filesystem.Extractor{fakeEx1, fakeEx2}, skipDirGlob: "{dir1,dir2}", - wantInv: []*extractor.Inventory{}, + wantPKGs: []*extractor.Package{}, wantStatus: []*plugin.Status{ {Name: "ex1", Version: 1, Status: success}, {Name: "ex2", Version: 2, Status: success}, @@ -347,7 +347,7 @@ func TestRunFS(t *testing.T) { desc: "No directories matched using glob", ex: []filesystem.Extractor{fakeEx1, fakeEx2}, skipDirGlob: "none", - wantInv: []*extractor.Inventory{ + wantPKGs: []*extractor.Package{ { Name: name1, Locations: []string{path1}, @@ -366,9 +366,9 @@ func TestRunFS(t *testing.T) { wantInodeCount: 6, }, { - desc: "Duplicate inventory results kept separate", - ex: []filesystem.Extractor{fakeEx1, fakeEx2WithInv1}, - wantInv: []*extractor.Inventory{ + desc: "Duplicate package results kept separate", + ex: []filesystem.Extractor{fakeEx1, fakeEx2WithPKG1}, + wantPKGs: []*extractor.Package{ { Name: name1, Locations: []string{path1}, @@ -377,7 +377,7 @@ func TestRunFS(t *testing.T) { { Name: name1, Locations: []string{path2}, - Extractor: fakeEx2WithInv1, + Extractor: fakeEx2WithPKG1, }, }, wantStatus: []*plugin.Status{ @@ -391,7 +391,7 @@ func TestRunFS(t *testing.T) { ex: []filesystem.Extractor{fakeEx1, fakeEx2}, // ScanRoot is CWD filesToExtract: []string{path.Join(cwd, path2)}, - wantInv: []*extractor.Inventory{ + wantPKGs: []*extractor.Package{ { Name: name2, Locations: []string{path2}, @@ -408,7 +408,7 @@ func TestRunFS(t *testing.T) { desc: "Extract specific file with absolute path", ex: []filesystem.Extractor{fakeEx1, fakeEx2}, filesToExtract: []string{path2}, - wantInv: []*extractor.Inventory{ + wantPKGs: []*extractor.Package{ { Name: name2, Locations: []string{path2}, @@ -427,7 +427,7 @@ func TestRunFS(t *testing.T) { // An Extractor that returns nil. fe.New("ex1", 1, []string{path1}, map[string]fe.NamesErr{path1: {nil, nil}}), }, - wantInv: []*extractor.Inventory{}, + wantPKGs: []*extractor.Package{}, wantStatus: []*plugin.Status{ {Name: "ex1", Version: 1, Status: success}, }, @@ -436,7 +436,7 @@ func TestRunFS(t *testing.T) { { desc: "Extraction fails with partial results", ex: []filesystem.Extractor{fakeExWithPartialResult}, - wantInv: []*extractor.Inventory{ + wantPKGs: []*extractor.Package{ { Name: name1, Locations: []string{path1}, @@ -455,7 +455,7 @@ func TestRunFS(t *testing.T) { ex: []filesystem.Extractor{ fe.New("ex1", 1, []string{path1}, map[string]fe.NamesErr{path1: {Names: nil, Err: errors.New("extraction failed")}}), }, - wantInv: []*extractor.Inventory{}, + wantPKGs: []*extractor.Package{}, wantStatus: []*plugin.Status{ {Name: "ex1", Version: 1, Status: &plugin.ScanStatus{ Status: plugin.ScanStatusFailed, FailureReason: fmt.Sprintf("%s: extraction failed", path1), @@ -471,7 +471,7 @@ func TestRunFS(t *testing.T) { path2: {Names: nil, Err: errors.New("extraction failed")}, }), }, - wantInv: []*extractor.Inventory{}, + wantPKGs: []*extractor.Package{}, wantStatus: []*plugin.Status{ {Name: "ex1", Version: 1, Status: &plugin.ScanStatus{ Status: plugin.ScanStatusFailed, @@ -484,7 +484,7 @@ func TestRunFS(t *testing.T) { desc: "More inodes visited than limit, Error", ex: []filesystem.Extractor{fakeEx1, fakeEx2}, maxInodes: 2, - wantInv: []*extractor.Inventory{}, + wantPKGs: []*extractor.Package{}, wantStatus: []*plugin.Status{ {Name: "ex1", Version: 1, Status: success}, {Name: "ex2", Version: 2, Status: success}, @@ -496,7 +496,7 @@ func TestRunFS(t *testing.T) { desc: "Less inodes visited than limit, no Error", ex: []filesystem.Extractor{fakeEx1, fakeEx2}, maxInodes: 6, - wantInv: []*extractor.Inventory{ + wantPKGs: []*extractor.Package{ { Name: name1, Locations: []string{path1}, @@ -517,7 +517,7 @@ func TestRunFS(t *testing.T) { { desc: "Extractors successful store absolute path when requested", ex: []filesystem.Extractor{fakeEx1, fakeEx2}, - wantInv: []*extractor.Inventory{ + wantPKGs: []*extractor.Package{ { Name: name1, Locations: []string{filepath.Join(cwd, path1)}, @@ -573,7 +573,7 @@ func TestRunFS(t *testing.T) { if err = wc.UpdateScanRoot(cwd, fsys); err != nil { t.Fatalf("wc.UpdateScanRoot(..., %v): %v", fsys, err) } - gotInv, gotStatus, err := filesystem.RunFS(context.Background(), config, wc) + gotPKGs, gotStatus, err := filesystem.RunFS(context.Background(), config, wc) if diff := cmp.Diff(tc.wantErr, err, cmpopts.EquateErrors()); diff != "" { t.Errorf("extractor.Run(%v) error got diff (-want +got):\n%s", tc.ex, diff) } @@ -583,11 +583,11 @@ func TestRunFS(t *testing.T) { } // The order of the locations doesn't matter. - for _, i := range gotInv { - sort.Strings(i.Locations) + for _, p := range gotPKGs { + sort.Strings(p.Locations) } - if diff := cmp.Diff(tc.wantInv, gotInv, cmpopts.SortSlices(invLess), fe.AllowUnexported, cmpopts.EquateErrors()); diff != "" { + if diff := cmp.Diff(tc.wantPKGs, gotPKGs, cmpopts.SortSlices(pkgLess), fe.AllowUnexported, cmpopts.EquateErrors()); diff != "" { t.Errorf("extractor.Run(%v): unexpected findings (-want +got):\n%s", tc.ex, diff) } @@ -609,7 +609,7 @@ type fakeCollector struct { func (c *fakeCollector) AfterInodeVisited(path string) { c.AfterInodeVisitedCount++ } -func invLess(i1, i2 *extractor.Inventory) bool { +func pkgLess(i1, i2 *extractor.Package) bool { if i1.Name != i2.Name { return i1.Name < i2.Name } @@ -701,13 +701,13 @@ func TestRunFS_ReadError(t *testing.T) { if err := wc.UpdateScanRoot(".", fsys); err != nil { t.Fatalf("wc.UpdateScanRoot(%v): %v", config, err) } - gotInv, gotStatus, err := filesystem.RunFS(context.Background(), config, wc) + gotPKGs, gotStatus, err := filesystem.RunFS(context.Background(), config, wc) if err != nil { t.Fatalf("extractor.Run(%v): %v", ex, err) } - if len(gotInv) > 0 { - t.Errorf("extractor.Run(%v): expected empty inventory, got %v", ex, gotInv) + if len(gotPKGs) > 0 { + t.Errorf("extractor.Run(%v): expected empty packages, got %v", ex, gotPKGs) } if diff := cmp.Diff(wantStatus, gotStatus); diff != "" { diff --git a/extractor/filesystem/language/cpp/conanlock/conanlock-v1-revisions_test.go b/extractor/filesystem/language/cpp/conanlock/conanlock-v1-revisions_test.go index 09f12662..efc2b4b8 100644 --- a/extractor/filesystem/language/cpp/conanlock/conanlock-v1-revisions_test.go +++ b/extractor/filesystem/language/cpp/conanlock/conanlock-v1-revisions_test.go @@ -33,14 +33,14 @@ func TestExtractor_Extract_v1_revisions(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/empty.v1.revisions.json", }, - WantInventory: []*extractor.Inventory{}, + WantPackages: []*extractor.Package{}, }, { Name: "one package", InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/one-package.v1.revisions.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "zlib", Version: "1.2.11", @@ -56,7 +56,7 @@ func TestExtractor_Extract_v1_revisions(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/no-name.v1.revisions.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "zlib", Version: "1.2.11", @@ -72,7 +72,7 @@ func TestExtractor_Extract_v1_revisions(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/two-packages.v1.revisions.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "zlib", Version: "1.2.11", @@ -96,7 +96,7 @@ func TestExtractor_Extract_v1_revisions(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/nested-dependencies.v1.revisions.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "zlib", Version: "1.2.13", @@ -144,7 +144,7 @@ func TestExtractor_Extract_v1_revisions(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/one-package-dev.v1.revisions.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "ninja", Version: "1.11.1", @@ -171,7 +171,7 @@ func TestExtractor_Extract_v1_revisions(t *testing.T) { return } - if diff := cmp.Diff(tt.WantInventory, got, cmpopts.SortSlices(extracttest.InventoryCmpLess)); diff != "" { + if diff := cmp.Diff(tt.WantPackages, got, cmpopts.SortSlices(extracttest.PackageCmpLess)); diff != "" { t.Errorf("%s.Extract(%q) diff (-want +got):\n%s", extr.Name(), tt.InputConfig.Path, diff) } }) diff --git a/extractor/filesystem/language/cpp/conanlock/conanlock-v1_test.go b/extractor/filesystem/language/cpp/conanlock/conanlock-v1_test.go index a69ccae0..64f23d7b 100644 --- a/extractor/filesystem/language/cpp/conanlock/conanlock-v1_test.go +++ b/extractor/filesystem/language/cpp/conanlock/conanlock-v1_test.go @@ -33,22 +33,22 @@ func TestExtractor_Extract_v1(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/not-json.txt", }, - WantInventory: nil, - WantErr: extracttest.ContainsErrStr{Str: "could not extract from"}, + WantPackages: nil, + WantErr: extracttest.ContainsErrStr{Str: "could not extract from"}, }, { Name: "no packages", InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/empty.v1.json", }, - WantInventory: []*extractor.Inventory{}, + WantPackages: []*extractor.Package{}, }, { Name: "one package", InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/one-package.v1.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "zlib", Version: "1.2.11", @@ -64,7 +64,7 @@ func TestExtractor_Extract_v1(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/no-name.v1.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "zlib", Version: "1.2.11", @@ -80,7 +80,7 @@ func TestExtractor_Extract_v1(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/two-packages.v1.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "zlib", Version: "1.2.11", @@ -104,7 +104,7 @@ func TestExtractor_Extract_v1(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/nested-dependencies.v1.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "zlib", Version: "1.2.13", @@ -152,7 +152,7 @@ func TestExtractor_Extract_v1(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/one-package-dev.v1.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "ninja", Version: "1.11.1", @@ -168,7 +168,7 @@ func TestExtractor_Extract_v1(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/old-format-0.0.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "zlib", Version: "1.2.11", @@ -184,7 +184,7 @@ func TestExtractor_Extract_v1(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/old-format-0.1.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "zlib", Version: "1.2.11", @@ -200,7 +200,7 @@ func TestExtractor_Extract_v1(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/old-format-0.2.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "zlib", Version: "1.2.11", @@ -216,7 +216,7 @@ func TestExtractor_Extract_v1(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/old-format-0.3.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "zlib", Version: "1.2.11", @@ -243,7 +243,7 @@ func TestExtractor_Extract_v1(t *testing.T) { return } - if diff := cmp.Diff(tt.WantInventory, got, cmpopts.SortSlices(extracttest.InventoryCmpLess)); diff != "" { + if diff := cmp.Diff(tt.WantPackages, got, cmpopts.SortSlices(extracttest.PackageCmpLess)); diff != "" { t.Errorf("%s.Extract(%q) diff (-want +got):\n%s", extr.Name(), tt.InputConfig.Path, diff) } }) diff --git a/extractor/filesystem/language/cpp/conanlock/conanlock-v2_test.go b/extractor/filesystem/language/cpp/conanlock/conanlock-v2_test.go index 8b6738f7..d3e86dd8 100644 --- a/extractor/filesystem/language/cpp/conanlock/conanlock-v2_test.go +++ b/extractor/filesystem/language/cpp/conanlock/conanlock-v2_test.go @@ -33,14 +33,14 @@ func TestExtractor_Extract_v2(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/empty.v2.json", }, - WantInventory: []*extractor.Inventory{}, + WantPackages: []*extractor.Package{}, }, { Name: "one package", InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/one-package.v2.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "zlib", Version: "1.2.11", @@ -56,7 +56,7 @@ func TestExtractor_Extract_v2(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/no-name.v2.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "zlib", Version: "1.2.11", @@ -72,7 +72,7 @@ func TestExtractor_Extract_v2(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/two-packages.v2.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "zlib", Version: "1.2.11", @@ -96,7 +96,7 @@ func TestExtractor_Extract_v2(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/nested-dependencies.v2.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "zlib", Version: "1.2.13", @@ -144,7 +144,7 @@ func TestExtractor_Extract_v2(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/one-package-dev.v2.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "ninja", Version: "1.11.1", @@ -171,7 +171,7 @@ func TestExtractor_Extract_v2(t *testing.T) { return } - if diff := cmp.Diff(tt.WantInventory, got, cmpopts.SortSlices(extracttest.InventoryCmpLess)); diff != "" { + if diff := cmp.Diff(tt.WantPackages, got, cmpopts.SortSlices(extracttest.PackageCmpLess)); diff != "" { t.Errorf("%s.Extract(%q) diff (-want +got):\n%s", extr.Name(), tt.InputConfig.Path, diff) } }) diff --git a/extractor/filesystem/language/cpp/conanlock/conanlock.go b/extractor/filesystem/language/cpp/conanlock/conanlock.go index 80b4f28e..78361744 100644 --- a/extractor/filesystem/language/cpp/conanlock/conanlock.go +++ b/extractor/filesystem/language/cpp/conanlock/conanlock.go @@ -45,7 +45,7 @@ type conanReference struct { TimeStamp string } -// conanGraphNode contains a subset of a graph entry that includes inventory information +// conanGraphNode contains a subset of a graph entry that includes package information type conanGraphNode struct { Pref string `json:"pref"` Ref string `json:"ref"` @@ -117,9 +117,9 @@ func parseConanReference(ref string) conanReference { return reference } -func parseConanV1Lock(lockfile conanLockFile) []*extractor.Inventory { +func parseConanV1Lock(lockfile conanLockFile) []*extractor.Package { var reference conanReference - packages := make([]*extractor.Inventory, 0, len(lockfile.GraphLock.Nodes)) + packages := make([]*extractor.Package, 0, len(lockfile.GraphLock.Nodes)) for _, node := range lockfile.GraphLock.Nodes { if node.Path != "" { @@ -141,7 +141,7 @@ func parseConanV1Lock(lockfile conanLockFile) []*extractor.Inventory { continue } - packages = append(packages, &extractor.Inventory{ + packages = append(packages, &extractor.Package{ Name: reference.Name, Version: reference.Version, Metadata: osv.DepGroupMetadata{ @@ -153,7 +153,7 @@ func parseConanV1Lock(lockfile conanLockFile) []*extractor.Inventory { return packages } -func parseConanRequires(packages *[]*extractor.Inventory, requires []string, group string) { +func parseConanRequires(packages *[]*extractor.Package, requires []string, group string) { for _, ref := range requires { reference := parseConanReference(ref) // skip entries with no name, they are most likely consumer's conanfiles @@ -162,7 +162,7 @@ func parseConanRequires(packages *[]*extractor.Inventory, requires []string, gro continue } - *packages = append(*packages, &extractor.Inventory{ + *packages = append(*packages, &extractor.Package{ Name: reference.Name, Version: reference.Version, Metadata: osv.DepGroupMetadata{ @@ -172,9 +172,9 @@ func parseConanRequires(packages *[]*extractor.Inventory, requires []string, gro } } -func parseConanV2Lock(lockfile conanLockFile) []*extractor.Inventory { +func parseConanV2Lock(lockfile conanLockFile) []*extractor.Package { packages := make( - []*extractor.Inventory, + []*extractor.Package, 0, uint64(len(lockfile.Requires))+uint64(len(lockfile.BuildRequires))+uint64(len(lockfile.PythonRequires)), ) @@ -186,7 +186,7 @@ func parseConanV2Lock(lockfile conanLockFile) []*extractor.Inventory { return packages } -func parseConanLock(lockfile conanLockFile) []*extractor.Inventory { +func parseConanLock(lockfile conanLockFile) []*extractor.Package { if lockfile.GraphLock.Nodes != nil { return parseConanV1Lock(lockfile) } @@ -217,7 +217,7 @@ func (e Extractor) FileRequired(api filesystem.FileAPI) bool { } // Extract extracts packages from conan.lock files passed through the scan input. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { var parsedLockfile *conanLockFile err := json.NewDecoder(input.Reader).Decode(&parsedLockfile) @@ -225,26 +225,26 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] return nil, fmt.Errorf("could not extract from %s: %w", input.Path, err) } - inv := parseConanLock(*parsedLockfile) + pkgs := parseConanLock(*parsedLockfile) - for i := range inv { - inv[i].Locations = []string{input.Path} + for i := range pkgs { + pkgs[i].Locations = []string{input.Path} } - return inv, nil + return pkgs, nil } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { return &purl.PackageURL{ Type: purl.TypeConan, - Name: i.Name, - Version: i.Version, + Name: p.Name, + Version: p.Version, } } // Ecosystem returns the OSV ecosystem ('ConanCenter') of the software extracted by this extractor. -func (e Extractor) Ecosystem(i *extractor.Inventory) string { +func (e Extractor) Ecosystem(p *extractor.Package) string { return "ConanCenter" } diff --git a/extractor/filesystem/language/dart/pubspec/pubspec.go b/extractor/filesystem/language/dart/pubspec/pubspec.go index dfac5132..73ee610b 100644 --- a/extractor/filesystem/language/dart/pubspec/pubspec.go +++ b/extractor/filesystem/language/dart/pubspec/pubspec.go @@ -90,16 +90,16 @@ func (e Extractor) FileRequired(api filesystem.FileAPI) bool { } // Extract extracts Dart packages from pubspec.lock files passed through the input. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { var parsedLockfile *pubspecLockfile if err := yaml.NewDecoder(input.Reader).Decode(&parsedLockfile); err != nil { return nil, fmt.Errorf("could not extract from %s: %w", input.Path, err) } - packages := make([]*extractor.Inventory, 0, len(parsedLockfile.Packages)) + packages := make([]*extractor.Package, 0, len(parsedLockfile.Packages)) for name, pkg := range parsedLockfile.Packages { - pkgDetails := &extractor.Inventory{ + pkgDetails := &extractor.Package{ Name: name, Version: pkg.Version, Locations: []string{input.Path}, @@ -120,16 +120,16 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] return packages, nil } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { return &purl.PackageURL{ Type: purl.TypePub, - Name: i.Name, - Version: i.Version, + Name: p.Name, + Version: p.Version, } } // Ecosystem returns the OSV Ecosystem of the software extracted by this extractor. -func (e Extractor) Ecosystem(i *extractor.Inventory) string { return "Pub" } +func (e Extractor) Ecosystem(p *extractor.Package) string { return "Pub" } var _ filesystem.Extractor = Extractor{} diff --git a/extractor/filesystem/language/dart/pubspec/pubspec_test.go b/extractor/filesystem/language/dart/pubspec/pubspec_test.go index 9249bcdd..8c5b8b04 100644 --- a/extractor/filesystem/language/dart/pubspec/pubspec_test.go +++ b/extractor/filesystem/language/dart/pubspec/pubspec_test.go @@ -90,14 +90,14 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/no-packages.lock", }, - WantInventory: []*extractor.Inventory{}, + WantPackages: []*extractor.Package{}, }, { Name: "one package", InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/one-package.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "back_button_interceptor", Version: "6.0.1", @@ -114,7 +114,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/one-package-dev.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "build_runner", Version: "2.2.1", @@ -133,7 +133,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/two-packages.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "shelf", Version: "1.3.2", @@ -159,7 +159,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/mixed-packages.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "back_button_interceptor", Version: "6.0.1", @@ -205,7 +205,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/source-git.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "flutter_rust_bridge", Version: "1.32.0", @@ -258,7 +258,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/source-sdk.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "flutter_web_plugins", Version: "0.0.0", @@ -275,7 +275,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/source-path.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "maa_core", Version: "0.0.1", @@ -303,7 +303,7 @@ func TestExtractor_Extract(t *testing.T) { return } - if diff := cmp.Diff(tt.WantInventory, got, cmpopts.SortSlices(extracttest.InventoryCmpLess)); diff != "" { + if diff := cmp.Diff(tt.WantPackages, got, cmpopts.SortSlices(extracttest.PackageCmpLess)); diff != "" { t.Errorf("%s.Extract(%q) diff (-want +got):\n%s", extr.Name(), tt.InputConfig.Path, diff) } }) diff --git a/extractor/filesystem/language/dotnet/depsjson/depsjson.go b/extractor/filesystem/language/dotnet/depsjson/depsjson.go index cd15b99f..5c72dda3 100644 --- a/extractor/filesystem/language/dotnet/depsjson/depsjson.go +++ b/extractor/filesystem/language/dotnet/depsjson/depsjson.go @@ -116,7 +116,7 @@ func (e Extractor) reportFileRequired(path string, result stats.FileRequiredResu } // Extract parses the deps.json file to extract .NET package dependencies. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { packages, err := e.extractFromInput(ctx, input) if e.stats != nil { var fileSizeBytes int64 @@ -146,7 +146,7 @@ type DepsJSON struct { } `json:"libraries"` } -func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { var deps DepsJSON decoder := json.NewDecoder(input.Reader) if err := decoder.Decode(&deps); err != nil { @@ -160,7 +160,7 @@ func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanI return nil, fmt.Errorf("empty deps.json file or no libraries found") } - var inventories []*extractor.Inventory + var packages []*extractor.Package for nameVersion, library := range deps.Libraries { // Split name and version from "package/version" format name, version := splitNameAndVersion(nameVersion) @@ -169,7 +169,7 @@ func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanI continue } // If the library type is "project", this is the root/main package. - i := &extractor.Inventory{ + p := &extractor.Package{ Name: name, Version: version, Metadata: &Metadata{ @@ -179,10 +179,10 @@ func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanI }, Locations: []string{input.Path}, } - inventories = append(inventories, i) + packages = append(packages, p) } - return inventories, nil + return packages, nil } // splitNameAndVersion splits the name and version from a "package/version" string. @@ -194,16 +194,16 @@ func splitNameAndVersion(nameVersion string) (string, string) { return parts[0], parts[1] } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { return &purl.PackageURL{ Type: purl.TypeNuget, - Name: i.Name, - Version: i.Version, + Name: p.Name, + Version: p.Version, } } // Ecosystem returns the OSV Ecosystem of the software extracted by this extractor. -func (Extractor) Ecosystem(i *extractor.Inventory) string { +func (Extractor) Ecosystem(p *extractor.Package) string { return "NuGet" } diff --git a/extractor/filesystem/language/dotnet/depsjson/depsjson_test.go b/extractor/filesystem/language/dotnet/depsjson/depsjson_test.go index 8a741606..91c3dbce 100644 --- a/extractor/filesystem/language/dotnet/depsjson/depsjson_test.go +++ b/extractor/filesystem/language/dotnet/depsjson/depsjson_test.go @@ -165,14 +165,14 @@ func TestExtract(t *testing.T) { path string osrelease string cfg depsjson.Config - wantInventory []*extractor.Inventory + wantPackages []*extractor.Package wantErr error wantResultMetric stats.FileExtractedResult }{ { name: "valid application1.deps.json file", path: "testdata/valid", - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "TestLibrary", Version: "1.0.0", @@ -221,7 +221,7 @@ func TestExtract(t *testing.T) { { name: "valid application1.deps.json file with an invalid package", path: "testdata/nopackagename", - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "TestLibrary", Version: "1.0.0", @@ -279,20 +279,20 @@ func TestExtract(t *testing.T) { got, err := e.Extract(context.Background(), input) - if diff := cmp.Diff(tt.wantInventory, got, cmpopts.SortSlices(invLess)); diff != "" { - t.Errorf("Inventory mismatch (-want +got):\n%s", diff) + if diff := cmp.Diff(tt.wantPackages, got, cmpopts.SortSlices(pkgLess)); diff != "" { + t.Errorf("Package mismatch (-want +got):\n%s", diff) } }) } } -func invLess(i1, i2 *extractor.Inventory) bool { +func pkgLess(i1, i2 *extractor.Package) bool { return i1.Name < i2.Name } func TestToPURL(t *testing.T) { e := depsjson.Extractor{} - i := &extractor.Inventory{ + p := &extractor.Package{ Name: "Name", Version: "1.2.3", Locations: []string{"location"}, @@ -302,8 +302,8 @@ func TestToPURL(t *testing.T) { Name: "Name", Version: "1.2.3", } - got := e.ToPURL(i) + got := e.ToPURL(p) if diff := cmp.Diff(want, got); diff != "" { - t.Errorf("ToPURL(%v) (-want +got):\n%s", i, diff) + t.Errorf("ToPURL(%v) (-want +got):\n%s", p, diff) } } diff --git a/extractor/filesystem/language/dotnet/packagesconfig/packagesconfig.go b/extractor/filesystem/language/dotnet/packagesconfig/packagesconfig.go index 06040f60..8df79f66 100644 --- a/extractor/filesystem/language/dotnet/packagesconfig/packagesconfig.go +++ b/extractor/filesystem/language/dotnet/packagesconfig/packagesconfig.go @@ -129,7 +129,7 @@ func (e Extractor) reportFileRequired(path string, result stats.FileRequiredResu } // Extract parses the packages.config file to extract .NET package dependencies. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { packages, err := e.extractFromInput(ctx, input) if e.stats != nil { var fileSizeBytes int64 @@ -155,7 +155,7 @@ type dotNETPackages struct { Packages []dotNETPackage `xml:"package"` } -func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { var packages dotNETPackages decoder := xml.NewDecoder(input.Reader) if err := decoder.Decode(&packages); err != nil { @@ -163,34 +163,33 @@ func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanI return nil, err } - var inventories []*extractor.Inventory + var result []*extractor.Package for _, pkg := range packages.Packages { if pkg.ID == "" || pkg.Version == "" { log.Warnf("Skipping package with missing name or version: %+v", pkg) continue } - i := &extractor.Inventory{ + result = append(result, &extractor.Package{ Name: pkg.ID, Version: pkg.Version, Locations: []string{input.Path}, - } - inventories = append(inventories, i) + }) } - return inventories, nil + return result, nil } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { return &purl.PackageURL{ Type: purl.TypeNuget, - Name: i.Name, - Version: i.Version, + Name: p.Name, + Version: p.Version, } } // Ecosystem returns the OSV Ecosystem of the software extracted by this extractor. -func (Extractor) Ecosystem(i *extractor.Inventory) string { +func (Extractor) Ecosystem(p *extractor.Package) string { return "NuGet" } diff --git a/extractor/filesystem/language/dotnet/packagesconfig/packagesconfig_test.go b/extractor/filesystem/language/dotnet/packagesconfig/packagesconfig_test.go index e38b60e7..b1cd36d9 100644 --- a/extractor/filesystem/language/dotnet/packagesconfig/packagesconfig_test.go +++ b/extractor/filesystem/language/dotnet/packagesconfig/packagesconfig_test.go @@ -180,7 +180,7 @@ func TestExtract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/valid", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "Microsoft.CodeDom.Providers.DotNetCompilerPlatform", Version: "1.0.0", @@ -205,7 +205,7 @@ func TestExtract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/noversion", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "Microsoft.CodeDom.Providers.DotNetCompilerPlatform", Version: "1.0.0", @@ -218,7 +218,7 @@ func TestExtract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/nopackage", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "Microsoft.CodeDom.Providers.DotNetCompilerPlatform", Version: "1.0.0", @@ -248,12 +248,12 @@ func TestExtract(t *testing.T) { return } - // Compare the expected inventory with the actual inventory - if diff := cmp.Diff(tt.WantInventory, got, cmpopts.SortSlices(extracttest.InventoryCmpLess)); diff != "" { + // Compare the expected package with the actual package + if diff := cmp.Diff(tt.WantPackages, got, cmpopts.SortSlices(extracttest.PackageCmpLess)); diff != "" { t.Errorf("%s.Extract(%q) diff (-want +got):\n%s", e.Name(), tt.InputConfig.Path, diff) } - if diff := cmp.Diff(tt.WantInventory, got, cmpopts.SortSlices(extracttest.InventoryCmpLess)); diff != "" { + if diff := cmp.Diff(tt.WantPackages, got, cmpopts.SortSlices(extracttest.PackageCmpLess)); diff != "" { t.Errorf("%s.Extract(%q) diff (-want +got):\n%s", e.Name(), tt.InputConfig.Path, diff) } }) @@ -262,7 +262,7 @@ func TestExtract(t *testing.T) { func TestToPURL(t *testing.T) { e := packagesconfig.Extractor{} - i := &extractor.Inventory{ + p := &extractor.Package{ Name: "Name", Version: "1.2.3", Locations: []string{"location"}, @@ -272,8 +272,8 @@ func TestToPURL(t *testing.T) { Name: "Name", Version: "1.2.3", } - got := e.ToPURL(i) + got := e.ToPURL(p) if diff := cmp.Diff(want, got); diff != "" { - t.Errorf("ToPURL(%v) (-want +got):\n%s", i, diff) + t.Errorf("ToPURL(%v) (-want +got):\n%s", p, diff) } } diff --git a/extractor/filesystem/language/dotnet/packageslockjson/packageslockjson.go b/extractor/filesystem/language/dotnet/packageslockjson/packageslockjson.go index a1304bb3..4a4d7ba9 100644 --- a/extractor/filesystem/language/dotnet/packageslockjson/packageslockjson.go +++ b/extractor/filesystem/language/dotnet/packageslockjson/packageslockjson.go @@ -130,8 +130,8 @@ func (e Extractor) reportFileRequired(path string, fileSizeBytes int64, result s } // Extract returns a list of dependencies in a packages.lock.json file. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { - inventory, err := e.extractFromInput(ctx, input) +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { + pkgs, err := e.extractFromInput(ctx, input) if e.stats != nil { var fileSizeBytes int64 if input.Info != nil { @@ -143,25 +143,25 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] FileSizeBytes: fileSizeBytes, }) } - return inventory, err + return pkgs, err } -func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { p, err := Parse(input.Reader) if err != nil { return nil, err } - var res []*extractor.Inventory - for _, pkgs := range p.Dependencies { - for pkgName, info := range pkgs { - inv := &extractor.Inventory{ + var res []*extractor.Package + for _, packages := range p.Dependencies { + for pkgName, info := range packages { + pkg := &extractor.Package{ Name: pkgName, Version: info.Resolved, Locations: []string{ input.Path, }, } - res = append(res, inv) + res = append(res, pkg) } } @@ -180,14 +180,14 @@ func Parse(r io.Reader) (PackagesLockJSON, error) { return p, nil } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { return &purl.PackageURL{ Type: purl.TypeNuget, - Name: i.Name, - Version: i.Version, + Name: p.Name, + Version: p.Version, } } // Ecosystem returns the OSV Ecosystem of the software extracted by this extractor. -func (Extractor) Ecosystem(i *extractor.Inventory) string { return "NuGet" } +func (Extractor) Ecosystem(p *extractor.Package) string { return "NuGet" } diff --git a/extractor/filesystem/language/dotnet/packageslockjson/packageslockjson_test.go b/extractor/filesystem/language/dotnet/packageslockjson/packageslockjson_test.go index 04866da1..bf4ba9ca 100644 --- a/extractor/filesystem/language/dotnet/packageslockjson/packageslockjson_test.go +++ b/extractor/filesystem/language/dotnet/packageslockjson/packageslockjson_test.go @@ -132,14 +132,14 @@ func TestExtractor(t *testing.T) { tests := []struct { name string path string - wantInventory []*extractor.Inventory + wantPackages []*extractor.Package wantErr error wantResultMetric stats.FileExtractedResult }{ { name: "valid packages.lock.json", path: "testdata/valid/packages.lock.json", - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "Core.Dep", Version: "1.24.0", @@ -222,8 +222,8 @@ func TestExtractor(t *testing.T) { t.Fatalf("Extract(%+v) error: got %v, want %v\n", test.name, err, test.wantErr) } - sort := func(a, b *extractor.Inventory) bool { return a.Name < b.Name } - if diff := cmp.Diff(test.wantInventory, got, cmpopts.SortSlices(sort)); diff != "" { + sort := func(a, b *extractor.Package) bool { return a.Name < b.Name } + if diff := cmp.Diff(test.wantPackages, got, cmpopts.SortSlices(sort)); diff != "" { t.Errorf("Extract(%s) (-want +got):\n%s", test.path, diff) } @@ -242,7 +242,7 @@ func TestExtractor(t *testing.T) { func TestToPURL(t *testing.T) { e := packageslockjson.Extractor{} - i := &extractor.Inventory{ + p := &extractor.Package{ Name: "Name", Version: "1.2.3", Locations: []string{"location"}, @@ -252,8 +252,8 @@ func TestToPURL(t *testing.T) { Name: "Name", Version: "1.2.3", } - got := e.ToPURL(i) + got := e.ToPURL(p) if diff := cmp.Diff(want, got); diff != "" { - t.Errorf("ToPURL(%v) (-want +got):\n%s", i, diff) + t.Errorf("ToPURL(%v) (-want +got):\n%s", p, diff) } } diff --git a/extractor/filesystem/language/elixir/mixlock/mixlock.go b/extractor/filesystem/language/elixir/mixlock/mixlock.go index 6bc48e05..e5933b74 100644 --- a/extractor/filesystem/language/elixir/mixlock/mixlock.go +++ b/extractor/filesystem/language/elixir/mixlock/mixlock.go @@ -119,7 +119,7 @@ func (e Extractor) reportFileRequired(path string, result stats.FileRequiredResu } // Extract parses the mix.lock file to extract Elixir package dependencies. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { packages, err := e.extractFromInput(ctx, input) if e.stats != nil { var fileSizeBytes int64 @@ -135,17 +135,17 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] return packages, err } -func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { - // Parse the Mix.lock file into a list of packages and return Inventory directly +func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { + // Parse the Mix.lock file into a list of packages and return Package directly return mixlockutils.ParseMixLockFile(input) } -// ToPURL converts an inventory created by this extractor into a PURL using mixlockutils. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { - return mixlockutils.ToPURL(i) +// ToPURL converts a package created by this extractor into a PURL using mixlockutils. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { + return mixlockutils.ToPURL(p) } // Ecosystem returns the OSV Ecosystem of the software extracted by this extractor. -func (Extractor) Ecosystem(i *extractor.Inventory) string { +func (Extractor) Ecosystem(p *extractor.Package) string { return "Hex" } diff --git a/extractor/filesystem/language/elixir/mixlock/mixlock_test.go b/extractor/filesystem/language/elixir/mixlock/mixlock_test.go index 2a1b8704..afac43be 100644 --- a/extractor/filesystem/language/elixir/mixlock/mixlock_test.go +++ b/extractor/filesystem/language/elixir/mixlock/mixlock_test.go @@ -166,7 +166,7 @@ func TestExtract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/valid", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "bunt", Version: "1.0.0", @@ -190,7 +190,7 @@ func TestExtract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/invalid", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "bunt", Version: "1.0.0", @@ -227,7 +227,7 @@ func TestExtract(t *testing.T) { return } - if diff := cmp.Diff(tt.WantInventory, got, cmpopts.SortSlices(extracttest.InventoryCmpLess)); diff != "" { + if diff := cmp.Diff(tt.WantPackages, got, cmpopts.SortSlices(extracttest.PackageCmpLess)); diff != "" { t.Errorf("%s.Extract(%q) diff (-want +got):\n%s", e.Name(), tt.InputConfig.Path, diff) } }) @@ -236,7 +236,7 @@ func TestExtract(t *testing.T) { func TestToPURL(t *testing.T) { e := elixir.Extractor{} - i := &extractor.Inventory{ + p := &extractor.Package{ Name: "Name", Version: "1.2.3", Locations: []string{"location"}, @@ -246,8 +246,8 @@ func TestToPURL(t *testing.T) { Name: "name", Version: "1.2.3", } - got := e.ToPURL(i) + got := e.ToPURL(p) if diff := cmp.Diff(want, got); diff != "" { - t.Errorf("ToPURL(%v) (-want +got):\n%s", i, diff) + t.Errorf("ToPURL(%v) (-want +got):\n%s", p, diff) } } diff --git a/extractor/filesystem/language/erlang/mixlock/mixlock.go b/extractor/filesystem/language/erlang/mixlock/mixlock.go index 2f6f7b9c..70a55edb 100644 --- a/extractor/filesystem/language/erlang/mixlock/mixlock.go +++ b/extractor/filesystem/language/erlang/mixlock/mixlock.go @@ -54,18 +54,18 @@ func (e Extractor) FileRequired(api filesystem.FileAPI) bool { } // Extract extracts packages from Erlang mix.lock files passed through the scan input. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { // Parse the Mix.lock file using mixlockutils return mixlockutils.ParseMixLockFile(input) } -// ToPURL converts an inventory created by this extractor into a PURL using mixlockutils. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { - return mixlockutils.ToPURL(i) +// ToPURL converts a package created by this extractor into a PURL using mixlockutils. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { + return mixlockutils.ToPURL(p) } // Ecosystem returns the OSV Ecosystem of the software extracted by this extractor. -func (e Extractor) Ecosystem(i *extractor.Inventory) string { +func (e Extractor) Ecosystem(p *extractor.Package) string { return "Hex" } diff --git a/extractor/filesystem/language/erlang/mixlock/mixlock_test.go b/extractor/filesystem/language/erlang/mixlock/mixlock_test.go index 8494a1c6..3d6ed4d6 100644 --- a/extractor/filesystem/language/erlang/mixlock/mixlock_test.go +++ b/extractor/filesystem/language/erlang/mixlock/mixlock_test.go @@ -81,7 +81,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/one-package.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "plug", Version: "1.11.1", @@ -97,7 +97,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/two-packages.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "plug", Version: "1.11.1", @@ -121,7 +121,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/many.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "backoff", Version: "1.1.6", @@ -297,7 +297,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/git.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "foe", Version: "", @@ -340,7 +340,7 @@ func TestExtractor_Extract(t *testing.T) { return } - if diff := cmp.Diff(tt.WantInventory, got, cmpopts.SortSlices(extracttest.InventoryCmpLess)); diff != "" { + if diff := cmp.Diff(tt.WantPackages, got, cmpopts.SortSlices(extracttest.PackageCmpLess)); diff != "" { t.Errorf("%s.Extract(%q) diff (-want +got):\n%s", extr.Name(), tt.InputConfig.Path, diff) } }) diff --git a/extractor/filesystem/language/erlang/mixlock/mixlockutils/mixlockutils.go b/extractor/filesystem/language/erlang/mixlock/mixlockutils/mixlockutils.go index e9441c24..02381d59 100644 --- a/extractor/filesystem/language/erlang/mixlock/mixlockutils/mixlockutils.go +++ b/extractor/filesystem/language/erlang/mixlock/mixlockutils/mixlockutils.go @@ -43,10 +43,10 @@ type Package struct { } // ParseMixLockFile extracts packages from Erlang Mix.lock files passed through the scan input. -func ParseMixLockFile(input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func ParseMixLockFile(input *filesystem.ScanInput) ([]*extractor.Package, error) { scanner := bufio.NewScanner(input.Reader) - var inventories []*extractor.Inventory + var packages []*extractor.Package for scanner.Scan() { line := scanner.Text() @@ -78,8 +78,8 @@ func ParseMixLockFile(input *filesystem.ScanInput) ([]*extractor.Inventory, erro commit = match[5] } - // Directly appending to inventories - inventories = append(inventories, &extractor.Inventory{ + // Directly appending to packages + packages = append(packages, &extractor.Package{ Name: name, Version: version, Locations: []string{input.Path}, @@ -93,14 +93,14 @@ func ParseMixLockFile(input *filesystem.ScanInput) ([]*extractor.Inventory, erro return nil, fmt.Errorf("error while scanning %s: %w", input.Path, err) } - return inventories, nil + return packages, nil } // ToPURL converts a package into a PURL. -func ToPURL(i *extractor.Inventory) *purl.PackageURL { +func ToPURL(p *extractor.Package) *purl.PackageURL { return &purl.PackageURL{ Type: purl.TypeHex, - Name: strings.ToLower(i.Name), - Version: i.Version, + Name: strings.ToLower(p.Name), + Version: p.Version, } } diff --git a/extractor/filesystem/language/golang/gobinary/gobinary.go b/extractor/filesystem/language/golang/gobinary/gobinary.go index 7c0185fc..50695d04 100644 --- a/extractor/filesystem/language/golang/gobinary/gobinary.go +++ b/extractor/filesystem/language/golang/gobinary/gobinary.go @@ -119,7 +119,7 @@ func (e Extractor) reportFileRequired(path string, fileSizeBytes int64, result s } // Extract returns a list of installed third party dependencies in a Go binary. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { var readerAt io.ReaderAt if fileWithReaderAt, ok := input.Reader.(io.ReaderAt); ok { readerAt = fileWithReaderAt @@ -136,12 +136,12 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] if err != nil { log.Debugf("error parsing the contents of Go binary (%s) for extraction: %v", input.Path, err) e.reportFileExtracted(input.Path, input.Info, err) - return []*extractor.Inventory{}, nil + return []*extractor.Package{}, nil } - inventory, err := e.extractPackagesFromBuildInfo(binfo, input.Path) + pkg, err := e.extractPackagesFromBuildInfo(binfo, input.Path) e.reportFileExtracted(input.Path, input.Info, err) - return inventory, err + return pkg, err } func (e Extractor) reportFileExtracted(path string, fileinfo fs.FileInfo, err error) { @@ -159,15 +159,15 @@ func (e Extractor) reportFileExtracted(path string, fileinfo fs.FileInfo, err er }) } -func (e *Extractor) extractPackagesFromBuildInfo(binfo *buildinfo.BuildInfo, filename string) ([]*extractor.Inventory, error) { - res := []*extractor.Inventory{} +func (e *Extractor) extractPackagesFromBuildInfo(binfo *buildinfo.BuildInfo, filename string) ([]*extractor.Package, error) { + res := []*extractor.Package{} validatedGoVers, err := validateGoVersion(binfo.GoVersion) if err != nil { log.Warnf("failed to validate the Go version from buildinfo (%v): %v", binfo, err) } if validatedGoVers != "" { - res = append(res, &extractor.Inventory{ + res = append(res, &extractor.Package{ Name: "go", Version: validatedGoVers, Locations: []string{filename}, @@ -182,7 +182,7 @@ func (e *Extractor) extractPackagesFromBuildInfo(binfo *buildinfo.BuildInfo, fil pkgVers = strings.TrimPrefix(pkgVers, "v") - pkg := &extractor.Inventory{ + pkg := &extractor.Package{ Name: pkgName, Version: pkgVers, Locations: []string{filename}, @@ -219,14 +219,14 @@ func parseDependency(d *debug.Module) (string, string) { return dep.Path, dep.Version } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { return &purl.PackageURL{ Type: purl.TypeGolang, - Name: i.Name, - Version: i.Version, + Name: p.Name, + Version: p.Version, } } // Ecosystem returns the OSV Ecosystem of the software extracted by this extractor. -func (Extractor) Ecosystem(i *extractor.Inventory) string { return "Go" } +func (Extractor) Ecosystem(p *extractor.Package) string { return "Go" } diff --git a/extractor/filesystem/language/golang/gobinary/gobinary_test.go b/extractor/filesystem/language/golang/gobinary/gobinary_test.go index af2b22c1..a0994cb3 100644 --- a/extractor/filesystem/language/golang/gobinary/gobinary_test.go +++ b/extractor/filesystem/language/golang/gobinary/gobinary_test.go @@ -144,94 +144,94 @@ func TestExtract(t *testing.T) { tests := []struct { name string path string - wantInventory []*extractor.Inventory + wantPackages []*extractor.Package wantErr error wantResultMetric stats.FileExtractedResult }{ { - name: "binary_with_module_replacement-darwin-amd64", - path: "testdata/binary_with_module_replacement-darwin-amd64", - wantInventory: createInventories(append(BinaryWithModuleReplacementPackages, Toolchain), "testdata/binary_with_module_replacement-darwin-amd64"), + name: "binary_with_module_replacement-darwin-amd64", + path: "testdata/binary_with_module_replacement-darwin-amd64", + wantPackages: createPackages(append(BinaryWithModuleReplacementPackages, Toolchain), "testdata/binary_with_module_replacement-darwin-amd64"), }, { - name: "binary_with_module_replacement-darwin-arm64", - path: "testdata/binary_with_module_replacement-darwin-arm64", - wantInventory: createInventories(append(BinaryWithModuleReplacementPackages, Toolchain), "testdata/binary_with_module_replacement-darwin-arm64"), + name: "binary_with_module_replacement-darwin-arm64", + path: "testdata/binary_with_module_replacement-darwin-arm64", + wantPackages: createPackages(append(BinaryWithModuleReplacementPackages, Toolchain), "testdata/binary_with_module_replacement-darwin-arm64"), }, { - name: "binary_with_module_replacement-linux-386", - path: "testdata/binary_with_module_replacement-linux-386", - wantInventory: createInventories(append(BinaryWithModuleReplacementPackages, Toolchain), "testdata/binary_with_module_replacement-linux-386"), + name: "binary_with_module_replacement-linux-386", + path: "testdata/binary_with_module_replacement-linux-386", + wantPackages: createPackages(append(BinaryWithModuleReplacementPackages, Toolchain), "testdata/binary_with_module_replacement-linux-386"), }, { - name: "binary_with_module_replacement-linux-amd64", - path: "testdata/binary_with_module_replacement-linux-amd64", - wantInventory: createInventories(append(BinaryWithModuleReplacementPackages, Toolchain), "testdata/binary_with_module_replacement-linux-amd64"), + name: "binary_with_module_replacement-linux-amd64", + path: "testdata/binary_with_module_replacement-linux-amd64", + wantPackages: createPackages(append(BinaryWithModuleReplacementPackages, Toolchain), "testdata/binary_with_module_replacement-linux-amd64"), }, { - name: "binary_with_module_replacement-linux-arm64", - path: "testdata/binary_with_module_replacement-linux-arm64", - wantInventory: createInventories(append(BinaryWithModuleReplacementPackages, Toolchain), "testdata/binary_with_module_replacement-linux-arm64"), + name: "binary_with_module_replacement-linux-arm64", + path: "testdata/binary_with_module_replacement-linux-arm64", + wantPackages: createPackages(append(BinaryWithModuleReplacementPackages, Toolchain), "testdata/binary_with_module_replacement-linux-arm64"), }, { - name: "binary_with_module_replacement-windows-386", - path: "testdata/binary_with_module_replacement-windows-386", - wantInventory: createInventories(append(BinaryWithModuleReplacementPackages, Toolchain), "testdata/binary_with_module_replacement-windows-386"), + name: "binary_with_module_replacement-windows-386", + path: "testdata/binary_with_module_replacement-windows-386", + wantPackages: createPackages(append(BinaryWithModuleReplacementPackages, Toolchain), "testdata/binary_with_module_replacement-windows-386"), }, { - name: "binary_with_module_replacement-windows-amd64", - path: "testdata/binary_with_module_replacement-windows-amd64", - wantInventory: createInventories(append(BinaryWithModuleReplacementPackages, Toolchain), "testdata/binary_with_module_replacement-windows-amd64"), + name: "binary_with_module_replacement-windows-amd64", + path: "testdata/binary_with_module_replacement-windows-amd64", + wantPackages: createPackages(append(BinaryWithModuleReplacementPackages, Toolchain), "testdata/binary_with_module_replacement-windows-amd64"), }, { - name: "binary_with_module_replacement-windows-arm64", - path: "testdata/binary_with_module_replacement-windows-arm64", - wantInventory: createInventories(append(BinaryWithModuleReplacementPackages, Toolchain), "testdata/binary_with_module_replacement-windows-arm64"), + name: "binary_with_module_replacement-windows-arm64", + path: "testdata/binary_with_module_replacement-windows-arm64", + wantPackages: createPackages(append(BinaryWithModuleReplacementPackages, Toolchain), "testdata/binary_with_module_replacement-windows-arm64"), }, { - name: "binary_with_modules-darwin-amd64", - path: "testdata/binary_with_modules-darwin-amd64", - wantInventory: createInventories(append(BinaryWithModulesPackages, Toolchain), "testdata/binary_with_modules-darwin-amd64"), + name: "binary_with_modules-darwin-amd64", + path: "testdata/binary_with_modules-darwin-amd64", + wantPackages: createPackages(append(BinaryWithModulesPackages, Toolchain), "testdata/binary_with_modules-darwin-amd64"), }, { - name: "binary_with_modules-darwin-arm64", - path: "testdata/binary_with_modules-darwin-arm64", - wantInventory: createInventories(append(BinaryWithModulesPackages, Toolchain), "testdata/binary_with_modules-darwin-arm64"), + name: "binary_with_modules-darwin-arm64", + path: "testdata/binary_with_modules-darwin-arm64", + wantPackages: createPackages(append(BinaryWithModulesPackages, Toolchain), "testdata/binary_with_modules-darwin-arm64"), }, { - name: "binary_with_modules-linux-386", - path: "testdata/binary_with_modules-linux-386", - wantInventory: createInventories(append(BinaryWithModulesPackages, Toolchain), "testdata/binary_with_modules-linux-386"), + name: "binary_with_modules-linux-386", + path: "testdata/binary_with_modules-linux-386", + wantPackages: createPackages(append(BinaryWithModulesPackages, Toolchain), "testdata/binary_with_modules-linux-386"), }, { - name: "binary_with_modules-linux-amd64", - path: "testdata/binary_with_modules-linux-amd64", - wantInventory: createInventories(append(BinaryWithModulesPackages, Toolchain), "testdata/binary_with_modules-linux-amd64"), + name: "binary_with_modules-linux-amd64", + path: "testdata/binary_with_modules-linux-amd64", + wantPackages: createPackages(append(BinaryWithModulesPackages, Toolchain), "testdata/binary_with_modules-linux-amd64"), }, { - name: "binary_with_modules-linux-arm64", - path: "testdata/binary_with_modules-linux-arm64", - wantInventory: createInventories(append(BinaryWithModulesPackages, Toolchain), "testdata/binary_with_modules-linux-arm64"), + name: "binary_with_modules-linux-arm64", + path: "testdata/binary_with_modules-linux-arm64", + wantPackages: createPackages(append(BinaryWithModulesPackages, Toolchain), "testdata/binary_with_modules-linux-arm64"), }, { - name: "binary_with_modules-windows-386", - path: "testdata/binary_with_modules-windows-386", - wantInventory: createInventories(append(BinaryWithModulesPackagesWindows, Toolchain), "testdata/binary_with_modules-windows-386"), + name: "binary_with_modules-windows-386", + path: "testdata/binary_with_modules-windows-386", + wantPackages: createPackages(append(BinaryWithModulesPackagesWindows, Toolchain), "testdata/binary_with_modules-windows-386"), }, { - name: "binary_with_modules-windows-amd64", - path: "testdata/binary_with_modules-windows-amd64", - wantInventory: createInventories(append(BinaryWithModulesPackagesWindows, Toolchain), "testdata/binary_with_modules-windows-amd64"), + name: "binary_with_modules-windows-amd64", + path: "testdata/binary_with_modules-windows-amd64", + wantPackages: createPackages(append(BinaryWithModulesPackagesWindows, Toolchain), "testdata/binary_with_modules-windows-amd64"), }, { - name: "binary_with_modules-windows-arm64", - path: "testdata/binary_with_modules-windows-arm64", - wantInventory: createInventories(append(BinaryWithModulesPackagesWindows, Toolchain), "testdata/binary_with_modules-windows-arm64"), + name: "binary_with_modules-windows-arm64", + path: "testdata/binary_with_modules-windows-arm64", + wantPackages: createPackages(append(BinaryWithModulesPackagesWindows, Toolchain), "testdata/binary_with_modules-windows-arm64"), }, { name: "dummy file that fails to parse will log an error metric, but won't fail extraction", path: "testdata/dummy", - wantInventory: []*extractor.Inventory{}, + wantPackages: []*extractor.Package{}, wantResultMetric: stats.FileExtractedResultErrorUnknown, }, } @@ -258,8 +258,8 @@ func TestExtract(t *testing.T) { if err != tt.wantErr { t.Fatalf("Extract(%s) got error: %v, want error: %v", tt.path, err, tt.wantErr) } - sort := func(a, b *extractor.Inventory) bool { return a.Name < b.Name } - if diff := cmp.Diff(tt.wantInventory, got, cmpopts.SortSlices(sort)); diff != "" { + sort := func(a, b *extractor.Package) bool { return a.Name < b.Name } + if diff := cmp.Diff(tt.wantPackages, got, cmpopts.SortSlices(sort)); diff != "" { t.Fatalf("Extract(%s) (-want +got):\n%s", tt.path, diff) } @@ -282,7 +282,7 @@ func TestExtract(t *testing.T) { func TestToPURL(t *testing.T) { e := gobinary.Extractor{} - i := &extractor.Inventory{ + p := &extractor.Package{ Name: "name", Version: "1.2.3", Locations: []string{"location"}, @@ -292,9 +292,9 @@ func TestToPURL(t *testing.T) { Name: "name", Version: "1.2.3", } - got := e.ToPURL(i) + got := e.ToPURL(p) if diff := cmp.Diff(want, got); diff != "" { - t.Errorf("ToPURL(%v) (-want +got):\n%s", i, diff) + t.Errorf("ToPURL(%v) (-want +got):\n%s", p, diff) } } @@ -302,7 +302,7 @@ var ( // BinaryWithModulesPackagesWindows is a list of packages built into the // binary_with_modules-* testdata binaries, but only on Windows, where there // is an indirect dependency that is not built-in. - BinaryWithModulesPackagesWindows = []*extractor.Inventory{ + BinaryWithModulesPackagesWindows = []*extractor.Package{ // direct dependencies goPackage("github.com/ulikunitz/xz", "0.5.11"), goPackage("github.com/gin-gonic/gin", "1.8.1"), @@ -332,7 +332,7 @@ var ( // BinaryWithModuleReplacementPackages is a list of packages built into the // binary_with_module_replacement-* testdata binaries. - BinaryWithModuleReplacementPackages = []*extractor.Inventory{ + BinaryWithModuleReplacementPackages = []*extractor.Package{ // this binary replaces golang.org/x/xerrors => github.com/golang/xerrors goPackage("github.com/golang/xerrors", "0.0.0-20220907171357-04be3eba64a2"), } @@ -340,15 +340,15 @@ var ( Toolchain = goPackage("go", "1.22.0") ) -func goPackage(name, version string) *extractor.Inventory { - return &extractor.Inventory{Name: name, Version: version} +func goPackage(name, version string) *extractor.Package { + return &extractor.Package{Name: name, Version: version} } -func createInventories(invs []*extractor.Inventory, location string) []*extractor.Inventory { - res := []*extractor.Inventory{} - for _, i := range invs { - res = append(res, &extractor.Inventory{ - Name: i.Name, Version: i.Version, Locations: []string{location}, +func createPackages(pkgs []*extractor.Package, location string) []*extractor.Package { + res := []*extractor.Package{} + for _, p := range pkgs { + res = append(res, &extractor.Package{ + Name: p.Name, Version: p.Version, Locations: []string{location}, }) } return res diff --git a/extractor/filesystem/language/golang/gomod/gomod.go b/extractor/filesystem/language/golang/gomod/gomod.go index 23fa447e..abb0dc45 100644 --- a/extractor/filesystem/language/golang/gomod/gomod.go +++ b/extractor/filesystem/language/golang/gomod/gomod.go @@ -61,7 +61,7 @@ func (e Extractor) FileRequired(api filesystem.FileAPI) bool { } // Extract extracts packages from a go.mod file passed through the scan input. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { b, err := io.ReadAll(input.Reader) if err != nil { return nil, fmt.Errorf("could not read %s: %w", input.Path, err) @@ -76,12 +76,12 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] name string version string } - packages := map[mapKey]*extractor.Inventory{} + packages := map[mapKey]*extractor.Package{} for _, require := range parsedLockfile.Require { name := require.Mod.Path version := strings.TrimPrefix(require.Mod.Version, "v") - packages[mapKey{name: name, version: version}] = &extractor.Inventory{ + packages[mapKey{name: name, version: version}] = &extractor.Package{ Name: name, Version: version, Locations: []string{input.Path}, @@ -112,7 +112,7 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] } for _, replacement := range replacements { - packages[replacement] = &extractor.Inventory{ + packages[replacement] = &extractor.Package{ Name: replace.New.Path, Version: strings.TrimPrefix(replace.New.Version, "v"), Locations: []string{input.Path}, @@ -122,7 +122,7 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] // Add the Go stdlib as an explicit dependency. if parsedLockfile.Go != nil && parsedLockfile.Go.Version != "" { - packages[mapKey{name: "stdlib"}] = &extractor.Inventory{ + packages[mapKey{name: "stdlib"}] = &extractor.Package{ Name: "stdlib", Version: parsedLockfile.Go.Version, Locations: []string{input.Path}, @@ -131,24 +131,24 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] // The map values might have changed after replacement so we need to run another // deduplication pass. - dedupedPs := map[mapKey]*extractor.Inventory{} + dedupedPs := map[mapKey]*extractor.Package{} for _, p := range packages { dedupedPs[mapKey{name: p.Name, version: p.Version}] = p } return maps.Values(dedupedPs), nil } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { return &purl.PackageURL{ Type: purl.TypeGolang, - Name: i.Name, - Version: i.Version, + Name: p.Name, + Version: p.Version, } } // Ecosystem returns the OSV Ecosystem of the software extracted by this extractor. -func (e Extractor) Ecosystem(i *extractor.Inventory) string { +func (e Extractor) Ecosystem(p *extractor.Package) string { return "Go" } diff --git a/extractor/filesystem/language/golang/gomod/gomod_test.go b/extractor/filesystem/language/golang/gomod/gomod_test.go index f6a13f7e..ac82f537 100644 --- a/extractor/filesystem/language/golang/gomod/gomod_test.go +++ b/extractor/filesystem/language/golang/gomod/gomod_test.go @@ -82,14 +82,14 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/empty.mod", }, - WantInventory: []*extractor.Inventory{}, + WantPackages: []*extractor.Package{}, }, { Name: "one package", InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/one-package.mod", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "github.com/BurntSushi/toml", Version: "1.0.0", @@ -102,7 +102,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/two-packages.mod", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "github.com/BurntSushi/toml", Version: "1.0.0", @@ -125,7 +125,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/indirect-packages.mod", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "github.com/BurntSushi/toml", Version: "1.0.0", @@ -163,7 +163,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/replace-one.mod", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "example.com/fork/net", Version: "1.4.5", @@ -176,7 +176,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/replace-mixed.mod", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "example.com/fork/net", Version: "1.4.5", @@ -194,7 +194,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/replace-local.mod", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "./fork/net", Version: "", @@ -212,7 +212,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/replace-different.mod", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "example.com/fork/foe", Version: "1.4.5", @@ -230,7 +230,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/replace-not-required.mod", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "golang.org/x/net", Version: "0.5.6", @@ -248,7 +248,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/replace-no-version.mod", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "example.com/fork/net", Version: "1.4.5", @@ -272,7 +272,7 @@ func TestExtractor_Extract(t *testing.T) { return } - if diff := cmp.Diff(tt.WantInventory, got, cmpopts.SortSlices(extracttest.InventoryCmpLess)); diff != "" { + if diff := cmp.Diff(tt.WantPackages, got, cmpopts.SortSlices(extracttest.PackageCmpLess)); diff != "" { t.Errorf("%s.Extract(%q) diff (-want +got):\n%s", extr.Name(), tt.InputConfig.Path, diff) } }) diff --git a/extractor/filesystem/language/haskell/cabal/cabal.go b/extractor/filesystem/language/haskell/cabal/cabal.go index 8265783a..57484f69 100644 --- a/extractor/filesystem/language/haskell/cabal/cabal.go +++ b/extractor/filesystem/language/haskell/cabal/cabal.go @@ -124,8 +124,8 @@ func (e Extractor) reportFileRequired(path string, fileSizeBytes int64, result s } // Extract extracts packages from the cabal.project.freeze file. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { - inventory, err := e.extractFromInput(ctx, input) +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { + pkgs, err := e.extractFromInput(ctx, input) if e.stats != nil { var fileSizeBytes int64 @@ -138,19 +138,19 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] FileSizeBytes: fileSizeBytes, }) } - return inventory, err + return pkgs, err } var versionConstraintRe = regexp.MustCompile(`any\.(\S+) ==(\S+)`) -func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { s := bufio.NewScanner(input.Reader) - pkgs := []*extractor.Inventory{} + packages := []*extractor.Package{} for s.Scan() { // Return if canceled or exceeding deadline. if err := ctx.Err(); err != nil { - return pkgs, fmt.Errorf("%s halted at %q because of context error: %v", e.Name(), input.Path, err) + return packages, fmt.Errorf("%s halted at %q because of context error: %v", e.Name(), input.Path, err) } line := s.Text() @@ -165,31 +165,31 @@ func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanI pkgName := matches[1] pkgVersion := strings.TrimSuffix(matches[2], ",") - i := &extractor.Inventory{ + p := &extractor.Package{ Name: pkgName, Version: pkgVersion, Locations: []string{input.Path}, } - pkgs = append(pkgs, i) + packages = append(packages, p) } if s.Err() != nil { - return pkgs, fmt.Errorf("error while scanning cabal.project.freeze file from %v: %w", input.Path, s.Err()) + return packages, fmt.Errorf("error while scanning cabal.project.freeze file from %v: %w", input.Path, s.Err()) } } - return pkgs, nil + return packages, nil } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { return &purl.PackageURL{ Type: purl.TypeHaskell, - Name: i.Name, - Version: i.Version, + Name: p.Name, + Version: p.Version, } } // Ecosystem returns the OSV Ecosystem of the software extracted by this extractor. -func (Extractor) Ecosystem(i *extractor.Inventory) string { return "Hackage" } +func (Extractor) Ecosystem(p *extractor.Package) string { return "Hackage" } diff --git a/extractor/filesystem/language/haskell/cabal/cabal_test.go b/extractor/filesystem/language/haskell/cabal/cabal_test.go index 7990a184..bcd7d9fd 100644 --- a/extractor/filesystem/language/haskell/cabal/cabal_test.go +++ b/extractor/filesystem/language/haskell/cabal/cabal_test.go @@ -164,7 +164,7 @@ func TestExtract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/valid", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "AC-Angle", Version: "1.0", @@ -197,7 +197,7 @@ func TestExtract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/valid_2", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "AC-Angle", Version: "1.0", @@ -225,7 +225,7 @@ func TestExtract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/invalid", }, - WantInventory: []*extractor.Inventory{}, + WantPackages: []*extractor.Package{}, }, } @@ -248,7 +248,7 @@ func TestExtract(t *testing.T) { return } - if diff := cmp.Diff(tt.WantInventory, got, cmpopts.SortSlices(extracttest.InventoryCmpLess)); diff != "" { + if diff := cmp.Diff(tt.WantPackages, got, cmpopts.SortSlices(extracttest.PackageCmpLess)); diff != "" { t.Errorf("%s.Extract(%q) diff (-want +got):\n%s", e.Name(), tt.InputConfig.Path, diff) } }) @@ -257,7 +257,7 @@ func TestExtract(t *testing.T) { func TestToPURL(t *testing.T) { e := cabal.Extractor{} - i := &extractor.Inventory{ + p := &extractor.Package{ Name: "Name", Version: "1.2.3", Locations: []string{"location"}, @@ -267,8 +267,8 @@ func TestToPURL(t *testing.T) { Name: "Name", Version: "1.2.3", } - got := e.ToPURL(i) + got := e.ToPURL(p) if diff := cmp.Diff(want, got); diff != "" { - t.Errorf("ToPURL(%v) (-want +got):\n%s", i, diff) + t.Errorf("ToPURL(%v) (-want +got):\n%s", p, diff) } } diff --git a/extractor/filesystem/language/haskell/stacklock/stacklock.go b/extractor/filesystem/language/haskell/stacklock/stacklock.go index d5b37466..ef6279e2 100644 --- a/extractor/filesystem/language/haskell/stacklock/stacklock.go +++ b/extractor/filesystem/language/haskell/stacklock/stacklock.go @@ -124,8 +124,8 @@ func (e Extractor) reportFileRequired(path string, fileSizeBytes int64, result s } // Extract extracts packages from the stack.yaml.lock file. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { - inventory, err := e.extractFromInput(ctx, input) +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { + pkgs, err := e.extractFromInput(ctx, input) if e.stats != nil { var fileSizeBytes int64 @@ -138,19 +138,19 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] FileSizeBytes: fileSizeBytes, }) } - return inventory, err + return pkgs, err } var packageVersionRe = regexp.MustCompile(`hackage:\s*([a-zA-Z0-9\-]+)-([0-9.]+)@`) -func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { s := bufio.NewScanner(input.Reader) - pkgs := []*extractor.Inventory{} + packages := []*extractor.Package{} for s.Scan() { // Return if canceled or exceeding deadline. if err := ctx.Err(); err != nil { - return pkgs, fmt.Errorf("%s halted at %q because of context error: %v", e.Name(), input.Path, err) + return packages, fmt.Errorf("%s halted at %q because of context error: %v", e.Name(), input.Path, err) } line := strings.TrimSpace(s.Text()) @@ -164,31 +164,31 @@ func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanI pkgName := matches[1] pkgVersion := matches[2] - i := &extractor.Inventory{ + p := &extractor.Package{ Name: pkgName, Version: pkgVersion, Locations: []string{input.Path}, } - pkgs = append(pkgs, i) + packages = append(packages, p) } if s.Err() != nil { - return pkgs, fmt.Errorf("error while scanning cabal.project.freeze file from %v: %w", input.Path, s.Err()) + return packages, fmt.Errorf("error while scanning cabal.project.freeze file from %v: %w", input.Path, s.Err()) } } - return pkgs, nil + return packages, nil } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { return &purl.PackageURL{ Type: purl.TypeHaskell, - Name: i.Name, - Version: i.Version, + Name: p.Name, + Version: p.Version, } } // Ecosystem returns the OSV Ecosystem of the software extracted by this extractor. -func (Extractor) Ecosystem(i *extractor.Inventory) string { return "Hackage" } +func (Extractor) Ecosystem(p *extractor.Package) string { return "Hackage" } diff --git a/extractor/filesystem/language/haskell/stacklock/stacklock_test.go b/extractor/filesystem/language/haskell/stacklock/stacklock_test.go index 9278ea29..c64538e6 100644 --- a/extractor/filesystem/language/haskell/stacklock/stacklock_test.go +++ b/extractor/filesystem/language/haskell/stacklock/stacklock_test.go @@ -164,7 +164,7 @@ func TestExtract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/valid", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "fuzzyset", Version: "0.2.4", @@ -192,7 +192,7 @@ func TestExtract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/invalid", }, - WantInventory: []*extractor.Inventory{}, + WantPackages: []*extractor.Package{}, }, } @@ -215,7 +215,7 @@ func TestExtract(t *testing.T) { return } - if diff := cmp.Diff(tt.WantInventory, got, cmpopts.SortSlices(extracttest.InventoryCmpLess)); diff != "" { + if diff := cmp.Diff(tt.WantPackages, got, cmpopts.SortSlices(extracttest.PackageCmpLess)); diff != "" { t.Errorf("%s.Extract(%q) diff (-want +got):\n%s", e.Name(), tt.InputConfig.Path, diff) } }) @@ -224,7 +224,7 @@ func TestExtract(t *testing.T) { func TestToPURL(t *testing.T) { e := stacklock.Extractor{} - i := &extractor.Inventory{ + p := &extractor.Package{ Name: "Name", Version: "1.2.3", Locations: []string{"location"}, @@ -234,8 +234,8 @@ func TestToPURL(t *testing.T) { Name: "Name", Version: "1.2.3", } - got := e.ToPURL(i) + got := e.ToPURL(p) if diff := cmp.Diff(want, got); diff != "" { - t.Errorf("ToPURL(%v) (-want +got):\n%s", i, diff) + t.Errorf("ToPURL(%v) (-want +got):\n%s", p, diff) } } diff --git a/extractor/filesystem/language/java/archive/archive.go b/extractor/filesystem/language/java/archive/archive.go index 85499809..d72b93a7 100644 --- a/extractor/filesystem/language/java/archive/archive.go +++ b/extractor/filesystem/language/java/archive/archive.go @@ -165,8 +165,8 @@ func (e Extractor) reportFileRequired(path string, fileSizeBytes int64, result s } // Extract extracts java packages from archive files passed through input. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { - inventory, openedBytes, err := e.extractWithMax(ctx, input, 1, 0) +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { + pkgs, openedBytes, err := e.extractWithMax(ctx, input, 1, 0) if e.stats != nil { var fileSizeBytes int64 if input.Info != nil { @@ -179,14 +179,14 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] UncompressedBytes: openedBytes, }) } - return inventory, err + return pkgs, err } // extractWithMax recursively unzips and extracts packages from archive files starting at input. // // It returns early with an error if max depth or max opened bytes is reached. // Extracted packages are returned even if an error has occurred. -func (e Extractor) extractWithMax(ctx context.Context, input *filesystem.ScanInput, depth int, openedBytes int64) ([]*extractor.Inventory, int64, error) { +func (e Extractor) extractWithMax(ctx context.Context, input *filesystem.ScanInput, depth int, openedBytes int64) ([]*extractor.Package, int64, error) { // Return early if any max/min thresholds are hit. if depth > e.maxZipDepth { return nil, openedBytes, fmt.Errorf("%s reached max zip depth %d at %q", e.Name(), depth, input.Path) @@ -246,19 +246,19 @@ func (e Extractor) extractWithMax(ctx context.Context, input *filesystem.ScanInp // Aggregate errors while looping through files in the zip to continue extraction of other files. errs := []error{} - inventory := []*extractor.Inventory{} - inventoryPom := []*extractor.Inventory{} - inventoryManifest := []*extractor.Inventory{} + pkgs := []*extractor.Package{} + packagePom := []*extractor.Package{} + packageManifest := []*extractor.Package{} for _, file := range zipReader.File { // Return if canceled or exceeding deadline. if errors.Is(ctx.Err(), context.DeadlineExceeded) { // Ignore local findings from pom and manifest, as they are incomplete. - return inventory, openedBytes, fmt.Errorf("%s halted at %q because context deadline exceeded", e.Name(), input.Path) + return pkgs, openedBytes, fmt.Errorf("%s halted at %q because context deadline exceeded", e.Name(), input.Path) } if errors.Is(ctx.Err(), context.Canceled) { // Ignore local findings from pom and manifest, as they are incomplete. - return inventory, openedBytes, fmt.Errorf("%s halted at %q because context was canceled", e.Name(), input.Path) + return pkgs, openedBytes, fmt.Errorf("%s halted at %q because context was canceled", e.Name(), input.Path) } path := filepath.Join(input.Path, file.Name) @@ -271,7 +271,7 @@ func (e Extractor) extractWithMax(ctx context.Context, input *filesystem.ScanInp continue } if pp.valid() { - inventoryPom = append(inventoryPom, &extractor.Inventory{ + packagePom = append(packagePom, &extractor.Package{ Name: pp.ArtifactID, Version: pp.Version, Metadata: &Metadata{ @@ -291,7 +291,7 @@ func (e Extractor) extractWithMax(ctx context.Context, input *filesystem.ScanInp continue } if mf.valid() { - inventoryManifest = append(inventoryManifest, &extractor.Inventory{ + packageManifest = append(packageManifest, &extractor.Package{ Name: mf.ArtifactID, Version: mf.Version, Metadata: &Metadata{ @@ -315,27 +315,27 @@ func (e Extractor) extractWithMax(ctx context.Context, input *filesystem.ScanInp // Do not need to handle error from f.Close() because it only happens if the file was previously closed. defer f.Close() subInput := &filesystem.ScanInput{Path: path, Info: file.FileInfo(), Reader: f} - var subInventory []*extractor.Inventory - subInventory, openedBytes, err = e.extractWithMax(ctx, subInput, depth+1, openedBytes) + var subPackage []*extractor.Package + subPackage, openedBytes, err = e.extractWithMax(ctx, subInput, depth+1, openedBytes) // Prepend the current input path - for i := range subInventory { - subInventory[i].Locations = append([]string{input.Path}, subInventory[i].Locations...) + for i := range subPackage { + subPackage[i].Locations = append([]string{input.Path}, subPackage[i].Locations...) } if err != nil { log.Errorf("%s failed to extract %q: %v", e.Name(), path, err) errs = append(errs, err) return } - inventory = append(inventory, subInventory...) + pkgs = append(pkgs, subPackage...) }() } } - inventory = append(inventory, inventoryPom...) + pkgs = append(pkgs, packagePom...) // If there is no pom.properties, try combining MANIFEST.MF and filename. - inventoryFilename := []*extractor.Inventory{} - if len(inventoryPom) == 0 && e.extractFromFilename { + packageFilename := []*extractor.Package{} + if len(packagePom) == 0 && e.extractFromFilename { p := ParseFilename(input.Path) if p != nil { log.Debugf("PropsFromFilename(%q): %+v", input.Path, p) @@ -353,15 +353,15 @@ func (e Extractor) extractWithMax(ctx context.Context, input *filesystem.ScanInp groupID = strings.ToLower(p.GroupID) } // If manifest.mf was found, use GroupID from manifest instead, if - // present. Then remove manifest from the Inventory. - if len(inventoryManifest) == 1 { - metadata := inventoryManifest[0].Metadata.(*Metadata) + // present. Then remove manifest from the Package. + if len(packageManifest) == 1 { + metadata := packageManifest[0].Metadata.(*Metadata) if metadata.GroupID != "" { groupID = metadata.GroupID - inventoryManifest = nil + packageManifest = nil } } - inventoryFilename = append(inventoryFilename, &extractor.Inventory{ + packageFilename = append(packageFilename, &extractor.Package{ Name: p.ArtifactID, Version: p.Version, Metadata: &Metadata{ @@ -373,15 +373,15 @@ func (e Extractor) extractWithMax(ctx context.Context, input *filesystem.ScanInp }) } } - inventory = append(inventory, inventoryFilename...) + pkgs = append(pkgs, packageFilename...) - if len(inventoryPom) == 0 && len(inventoryFilename) == 0 { - inventory = append(inventory, inventoryManifest...) + if len(packagePom) == 0 && len(packageFilename) == 0 { + pkgs = append(pkgs, packageManifest...) } // If nothing worked, return the hash. - if len(inventory) == 0 && sha1 != "" { - inventory = append(inventory, &extractor.Inventory{ + if len(pkgs) == 0 && sha1 != "" { + pkgs = append(pkgs, &extractor.Package{ Name: "unknown", Version: "unknown", Metadata: &Metadata{ @@ -396,10 +396,10 @@ func (e Extractor) extractWithMax(ctx context.Context, input *filesystem.ScanInp // Aggregate errors. err = multierr.Combine(errs...) if err != nil { - return inventory, openedBytes, fmt.Errorf("error(s) in extractor %s: %w", e.Name(), err) + return pkgs, openedBytes, fmt.Errorf("error(s) in extractor %s: %w", e.Name(), err) } - return inventory, openedBytes, err + return pkgs, openedBytes, err } // hashJar returns base64(sha1()) of the file. This is compatible to dev.deps. @@ -431,16 +431,16 @@ func isManifest(path string) bool { return strings.ToLower(filepath.Base(path)) == "manifest.mf" } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { - m := i.Metadata.(*Metadata) +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { + m := p.Metadata.(*Metadata) return &purl.PackageURL{ Type: purl.TypeMaven, Namespace: strings.ToLower(m.GroupID), Name: strings.ToLower(m.ArtifactID), - Version: i.Version, + Version: p.Version, } } // Ecosystem returns the OSV Ecosystem of the software extracted by this extractor. -func (Extractor) Ecosystem(i *extractor.Inventory) string { return "Maven" } +func (Extractor) Ecosystem(p *extractor.Package) string { return "Maven" } diff --git a/extractor/filesystem/language/java/archive/archive_test.go b/extractor/filesystem/language/java/archive/archive_test.go index 1ce5e6d7..aff63cc6 100644 --- a/extractor/filesystem/language/java/archive/archive_test.go +++ b/extractor/filesystem/language/java/archive/archive_test.go @@ -181,7 +181,7 @@ func TestExtract(t *testing.T) { cfg archive.Config path string contentPath string - want []*extractor.Inventory + want []*extractor.Package wantErr error wantResultMetric stats.FileExtractedResult }{ @@ -203,18 +203,18 @@ func TestExtract(t *testing.T) { name: "Jar file with no pom.properties", description: "Contains other files but no pom.properties.", path: filepath.FromSlash("testdata/no_pom_properties.jar"), - want: []*extractor.Inventory{}, + want: []*extractor.Package{}, }, { name: "Jar file with invalid pom.properties", description: "Contains a pom.properties which is missing the `groupId` field and so it is ignored.", path: filepath.FromSlash("testdata/pom_missing_group_id.jar"), - want: []*extractor.Inventory{}, + want: []*extractor.Package{}, }, { name: "Jar file with pom.properties", path: filepath.FromSlash("testdata/simple.jar"), - want: []*extractor.Inventory{{ + want: []*extractor.Package{{ Name: "package-name", Version: "1.2.3", Metadata: &archive.Metadata{ArtifactID: "package-name", GroupID: "com.some.package"}, @@ -231,7 +231,7 @@ func TestExtract(t *testing.T) { cfg: archive.Config{ ExtractFromFilename: true, }, - want: []*extractor.Inventory{}, + want: []*extractor.Package{}, }, { name: "Jar file with pom.properties, IdentifyByFilename enabled", @@ -240,7 +240,7 @@ func TestExtract(t *testing.T) { cfg: archive.Config{ ExtractFromFilename: true, }, - want: []*extractor.Inventory{{ + want: []*extractor.Package{{ Name: "package-name", Version: "1.2.3", Metadata: &archive.Metadata{ArtifactID: "package-name", GroupID: "com.some.package"}, @@ -257,7 +257,7 @@ func TestExtract(t *testing.T) { cfg: archive.Config{ ExtractFromFilename: true, }, - want: []*extractor.Inventory{{ + want: []*extractor.Package{{ Name: "no_pom_properties", Version: "2.4.0", Metadata: &archive.Metadata{ArtifactID: "no_pom_properties", GroupID: "no_pom_properties"}, @@ -274,7 +274,7 @@ func TestExtract(t *testing.T) { cfg: archive.Config{ ExtractFromFilename: true, }, - want: []*extractor.Inventory{{ + want: []*extractor.Package{{ Name: "no_pom_properties", Version: "2.4.0", Metadata: &archive.Metadata{ @@ -294,7 +294,7 @@ func TestExtract(t *testing.T) { cfg: archive.Config{ ExtractFromFilename: true, }, - want: []*extractor.Inventory{{ + want: []*extractor.Package{{ Name: "no_pom_properties", Version: "2.4.0", Metadata: &archive.Metadata{ @@ -315,7 +315,7 @@ func TestExtract(t *testing.T) { cfg: archive.Config{ ExtractFromFilename: true, }, - want: []*extractor.Inventory{{ + want: []*extractor.Package{{ Name: "pom_missing_group_id", Version: "2.4.0", Metadata: &archive.Metadata{ArtifactID: "pom_missing_group_id", GroupID: "pom_missing_group_id"}, @@ -331,7 +331,7 @@ func TestExtract(t *testing.T) { cfg: archive.Config{ ExtractFromFilename: true, }, - want: []*extractor.Inventory{{ + want: []*extractor.Package{{ Name: "org.eclipse.sisu.inject", Version: "0.3.5", Metadata: &archive.Metadata{ArtifactID: "org.eclipse.sisu.inject", GroupID: "org.eclipse.sisu"}, @@ -344,7 +344,7 @@ func TestExtract(t *testing.T) { name: "Nested jars with pom.properties at depth 10", path: filepath.FromSlash("testdata/nested_at_10.jar"), cfg: archive.Config{HashJars: true}, - want: []*extractor.Inventory{{ + want: []*extractor.Package{{ Name: "package-name", Version: "1.2.3", Metadata: &archive.Metadata{ @@ -371,14 +371,14 @@ func TestExtract(t *testing.T) { name: "Nested jars with pom.properties at depth 100", description: "Returns error with no results because max depth is reached before getting to pom.properties", path: filepath.FromSlash("testdata/nested_at_100.jar"), - want: []*extractor.Inventory{}, + want: []*extractor.Package{}, wantErr: errAny, }, { name: "Jar file with pom.properties at multiple depths", description: "A jar file with pom.properties at complex.jar/pom.properties and another at complex.jar/BOOT-INF/lib/inner.jar/pom.properties", path: filepath.FromSlash("testdata/complex.jar"), - want: []*extractor.Inventory{ + want: []*extractor.Package{ { Name: "package-name", Version: "1.2.3", @@ -408,7 +408,7 @@ func TestExtract(t *testing.T) { Stats: testcollector.New(), }, path: filepath.FromSlash("testdata/complex.jar"), - want: []*extractor.Inventory{{ + want: []*extractor.Package{{ Name: "package-name", Version: "1.2.3", Metadata: &archive.Metadata{ArtifactID: "package-name", GroupID: "com.some.package"}, @@ -424,7 +424,7 @@ func TestExtract(t *testing.T) { name: "Realistic jar file with pom.properties", path: filepath.FromSlash("testdata/guava-31.1-jre.jar"), cfg: archive.Config{HashJars: true}, - want: []*extractor.Inventory{ + want: []*extractor.Package{ { Name: "guava", Version: "31.1-jre", @@ -444,13 +444,13 @@ func TestExtract(t *testing.T) { { name: "Test MANIFEST.MF with no valid ArtifactID", path: filepath.FromSlash("testdata/com.google.src.yolo-0.1.2.jar"), - want: []*extractor.Inventory{}, + want: []*extractor.Package{}, }, { name: "Test MANIFEST.MF with symbolic name", path: filepath.FromSlash("testdata/manifest-symbolicname"), contentPath: filepath.FromSlash("testdata/manifest-symbolicname/MANIFEST.MF"), - want: []*extractor.Inventory{{ + want: []*extractor.Package{{ Name: "failureaccess", Version: "1.0.1", Metadata: &archive.Metadata{ @@ -467,7 +467,7 @@ func TestExtract(t *testing.T) { name: "Test invalid group or artifact id in manifest.mf", path: filepath.FromSlash("testdata/invalid-ids"), contentPath: filepath.FromSlash("testdata/invalid-ids/MANIFEST.MF"), - want: []*extractor.Inventory{{ + want: []*extractor.Package{{ Name: "correct.name", Version: "1.2.3", Metadata: &archive.Metadata{ @@ -484,7 +484,7 @@ func TestExtract(t *testing.T) { name: "Test artifact ID that is mapped to a known group ID", path: filepath.FromSlash("testdata/known-group-id"), contentPath: filepath.FromSlash("testdata/known-group-id/MANIFEST.MF"), - want: []*extractor.Inventory{{ + want: []*extractor.Package{{ Name: "spring-web", Version: "5.3.26", Metadata: &archive.Metadata{ @@ -502,7 +502,7 @@ func TestExtract(t *testing.T) { path: filepath.FromSlash("testdata/ivy-2.4.0.jar"), contentPath: filepath.FromSlash("testdata/combine-manifest-filename/MANIFEST.MF"), cfg: archive.Config{ExtractFromFilename: true}, - want: []*extractor.Inventory{{ + want: []*extractor.Package{{ Name: "ivy", Version: "2.4.0", Metadata: &archive.Metadata{ @@ -520,7 +520,7 @@ func TestExtract(t *testing.T) { path: filepath.FromSlash("testdata/no_pom_properties-2.4.0.jar"), contentPath: filepath.FromSlash("testdata/manifest-implementation-title/MANIFEST.MF"), cfg: archive.Config{ExtractFromFilename: true}, - want: []*extractor.Inventory{{ + want: []*extractor.Package{{ Name: "no_pom_properties", Version: "2.4.0", Metadata: &archive.Metadata{ @@ -540,7 +540,7 @@ func TestExtract(t *testing.T) { cfg: archive.Config{ ExtractFromFilename: true, }, - want: []*extractor.Inventory{{ + want: []*extractor.Package{{ Name: "axis", Version: "1.4", Metadata: &archive.Metadata{ArtifactID: "axis", GroupID: "org.apache.axis"}, @@ -592,7 +592,7 @@ func TestExtract(t *testing.T) { if !errors.Is(err, tt.wantErr) { t.Fatalf("Extract(%s) got error: %v, want error: %v", tt.path, err, tt.wantErr) } - sort := func(a, b *extractor.Inventory) bool { return a.Name < b.Name } + sort := func(a, b *extractor.Package) bool { return a.Name < b.Name } if diff := cmp.Diff(tt.want, got, cmpopts.SortSlices(sort)); diff != "" { t.Fatalf("Extract(%s) (-want +got):\n%s", tt.path, diff) } @@ -612,7 +612,7 @@ func TestExtract(t *testing.T) { func TestToPURL(t *testing.T) { e := archive.Extractor{} - i := &extractor.Inventory{ + p := &extractor.Package{ Name: "Name", Version: "1.2.3", Metadata: &archive.Metadata{ @@ -627,9 +627,9 @@ func TestToPURL(t *testing.T) { Namespace: "groupid", Version: "1.2.3", } - got := e.ToPURL(i) + got := e.ToPURL(p) if diff := cmp.Diff(want, got); diff != "" { - t.Errorf("ToPURL(%v) (-want +got):\n%s", i, diff) + t.Errorf("ToPURL(%v) (-want +got):\n%s", p, diff) } } diff --git a/extractor/filesystem/language/java/gradlelockfile/gradlelockfile.go b/extractor/filesystem/language/java/gradlelockfile/gradlelockfile.go index a1054e36..2727cddb 100644 --- a/extractor/filesystem/language/java/gradlelockfile/gradlelockfile.go +++ b/extractor/filesystem/language/java/gradlelockfile/gradlelockfile.go @@ -45,7 +45,7 @@ func isGradleLockFileDepLine(line string) bool { return !ret } -func parseToGradlePackageDetail(line string) (*extractor.Inventory, error) { +func parseToGradlePackageDetail(line string) (*extractor.Package, error) { parts := strings.SplitN(line, ":", 3) if len(parts) < 3 { return nil, fmt.Errorf("invalid line in gradle lockfile: %s", line) @@ -57,7 +57,7 @@ func parseToGradlePackageDetail(line string) (*extractor.Inventory, error) { } version = strings.SplitN(version, "=", 2)[0] - return &extractor.Inventory{ + return &extractor.Package{ Name: fmt.Sprintf("%s:%s", group, artifact), Version: version, Metadata: &javalockfile.Metadata{ @@ -92,8 +92,8 @@ func (e Extractor) FileRequired(api filesystem.FileAPI) bool { } // Extract extracts packages from Gradle files passed through the scan input. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { - pkgs := make([]*extractor.Inventory, 0) +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { + packages := make([]*extractor.Package, 0) scanner := bufio.NewScanner(input.Reader) for scanner.Scan() { @@ -109,29 +109,29 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] pkg.Locations = []string{input.Path} - pkgs = append(pkgs, pkg) + packages = append(packages, pkg) } if err := scanner.Err(); err != nil { return nil, fmt.Errorf("failed to read: %w", err) } - return pkgs, nil + return packages, nil } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { - m := i.Metadata.(*javalockfile.Metadata) +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { + m := p.Metadata.(*javalockfile.Metadata) return &purl.PackageURL{ Type: purl.TypeMaven, Namespace: strings.ToLower(m.GroupID), Name: strings.ToLower(m.ArtifactID), - Version: i.Version, + Version: p.Version, } } // Ecosystem returns the OSV ecosystem ('Maven') of the software extracted by this extractor. -func (e Extractor) Ecosystem(i *extractor.Inventory) string { +func (e Extractor) Ecosystem(p *extractor.Package) string { return "Maven" } diff --git a/extractor/filesystem/language/java/gradlelockfile/gradlelockfile_test.go b/extractor/filesystem/language/java/gradlelockfile/gradlelockfile_test.go index dfb7c427..02da3d84 100644 --- a/extractor/filesystem/language/java/gradlelockfile/gradlelockfile_test.go +++ b/extractor/filesystem/language/java/gradlelockfile/gradlelockfile_test.go @@ -95,21 +95,21 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/only-comments", }, - WantInventory: []*extractor.Inventory{}, + WantPackages: []*extractor.Package{}, }, { Name: "empty statement", InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/only-empty", }, - WantInventory: []*extractor.Inventory{}, + WantPackages: []*extractor.Package{}, }, { Name: "one package", InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/one-pkg", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "org.springframework.security:spring-security-crypto", Version: "5.7.3", @@ -126,7 +126,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/5-pkg", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "org.springframework.boot:spring-boot-autoconfigure", Version: "2.7.4", @@ -179,7 +179,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/with-bad-pkg", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "org.springframework.boot:spring-boot-autoconfigure", Version: "2.7.4", @@ -216,7 +216,7 @@ func TestExtractor_Extract(t *testing.T) { return } - if diff := cmp.Diff(tt.WantInventory, got, cmpopts.SortSlices(extracttest.InventoryCmpLess)); diff != "" { + if diff := cmp.Diff(tt.WantPackages, got, cmpopts.SortSlices(extracttest.PackageCmpLess)); diff != "" { t.Errorf("%s.Extract(%q) diff (-want +got):\n%s", extr.Name(), tt.InputConfig.Path, diff) } }) diff --git a/extractor/filesystem/language/java/gradleverificationmetadataxml/gradleverificationmetadataxml.go b/extractor/filesystem/language/java/gradleverificationmetadataxml/gradleverificationmetadataxml.go index 3aa6faa7..99f327b6 100644 --- a/extractor/filesystem/language/java/gradleverificationmetadataxml/gradleverificationmetadataxml.go +++ b/extractor/filesystem/language/java/gradleverificationmetadataxml/gradleverificationmetadataxml.go @@ -66,7 +66,7 @@ func (e Extractor) FileRequired(api filesystem.FileAPI) bool { } // Extract extracts packages from verification-metadata.xml files passed through the scan input. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { var parsedLockfile *gradleVerificationMetadataFile err := xml.NewDecoder(input.Reader).Decode(&parsedLockfile) @@ -75,10 +75,10 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] return nil, fmt.Errorf("could not extract from %s: %w", input.Path, err) } - pkgs := make([]*extractor.Inventory, 0, len(parsedLockfile.Components)) + packages := make([]*extractor.Package, 0, len(parsedLockfile.Components)) for _, component := range parsedLockfile.Components { - pkgs = append(pkgs, &extractor.Inventory{ + packages = append(packages, &extractor.Package{ Name: component.Group + ":" + component.Name, Version: component.Version, Metadata: &javalockfile.Metadata{ @@ -89,22 +89,22 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] }) } - return pkgs, nil + return packages, nil } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { - m := i.Metadata.(*javalockfile.Metadata) +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { + m := p.Metadata.(*javalockfile.Metadata) return &purl.PackageURL{ Type: purl.TypeMaven, Namespace: strings.ToLower(m.GroupID), Name: strings.ToLower(m.ArtifactID), - Version: i.Version, + Version: p.Version, } } // Ecosystem returns the OSV ecosystem ('Maven') of the software extracted by this extractor. -func (e Extractor) Ecosystem(i *extractor.Inventory) string { +func (e Extractor) Ecosystem(p *extractor.Package) string { return "Maven" } diff --git a/extractor/filesystem/language/java/gradleverificationmetadataxml/gradleverificationmetadataxml_test.go b/extractor/filesystem/language/java/gradleverificationmetadataxml/gradleverificationmetadataxml_test.go index 065dd919..e7cdb572 100644 --- a/extractor/filesystem/language/java/gradleverificationmetadataxml/gradleverificationmetadataxml_test.go +++ b/extractor/filesystem/language/java/gradleverificationmetadataxml/gradleverificationmetadataxml_test.go @@ -107,22 +107,22 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/not-xml.txt", }, - WantInventory: nil, - WantErr: extracttest.ContainsErrStr{Str: "could not extract from"}, + WantPackages: nil, + WantErr: extracttest.ContainsErrStr{Str: "could not extract from"}, }, { Name: "no packages", InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/empty.xml", }, - WantInventory: []*extractor.Inventory{}, + WantPackages: []*extractor.Package{}, }, { Name: "one package", InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/one-package.xml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "org.apache.pdfbox:pdfbox", Version: "2.0.17", @@ -136,7 +136,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/two-packages.xml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "org.apache.pdfbox:pdfbox", Version: "2.0.17", @@ -156,7 +156,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/multiple-versions.xml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "androidx.activity:activity", Version: "1.2.1", @@ -272,7 +272,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/odd-versions.xml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "com.google:google", Version: "1", @@ -462,7 +462,7 @@ func TestExtractor_Extract(t *testing.T) { return } - if diff := cmp.Diff(tt.WantInventory, got, cmpopts.SortSlices(extracttest.InventoryCmpLess)); diff != "" { + if diff := cmp.Diff(tt.WantPackages, got, cmpopts.SortSlices(extracttest.PackageCmpLess)); diff != "" { t.Errorf("%s.Extract(%q) diff (-want +got):\n%s", extr.Name(), tt.InputConfig.Path, diff) } }) diff --git a/extractor/filesystem/language/java/pomxml/pomxml.go b/extractor/filesystem/language/java/pomxml/pomxml.go index b8350cf1..e0eea833 100644 --- a/extractor/filesystem/language/java/pomxml/pomxml.go +++ b/extractor/filesystem/language/java/pomxml/pomxml.go @@ -157,7 +157,7 @@ func (e Extractor) FileRequired(api filesystem.FileAPI) bool { } // Extract extracts packages from pom.xml files passed through the scan input. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { var parsedLockfile *mavenLockFile err := xml.NewDecoder(input.Reader).Decode(&parsedLockfile) @@ -166,7 +166,7 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] return nil, fmt.Errorf("could not extract from %s: %w", input.Path, err) } - details := map[string]*extractor.Inventory{} + details := map[string]*extractor.Package{} for _, lockPackage := range parsedLockfile.ManagedDependencies { finalName := lockPackage.GroupID + ":" + lockPackage.ArtifactID @@ -176,7 +176,7 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] DepGroupVals: []string{}, } - pkgDetails := &extractor.Inventory{ + pkgDetails := &extractor.Package{ Name: finalName, Version: lockPackage.ResolveVersion(*parsedLockfile), Locations: []string{input.Path}, @@ -199,7 +199,7 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] Classifier: lockPackage.Classifier, DepGroupVals: []string{}, } - pkgDetails := &extractor.Inventory{ + pkgDetails := &extractor.Package{ Name: finalName, Version: lockPackage.ResolveVersion(*parsedLockfile), Locations: []string{input.Path}, @@ -215,14 +215,14 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] return maps.Values(details), nil } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { - m := i.Metadata.(*javalockfile.Metadata) +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { + m := p.Metadata.(*javalockfile.Metadata) return &purl.PackageURL{ Type: purl.TypeMaven, Namespace: strings.ToLower(m.GroupID), Name: strings.ToLower(m.ArtifactID), - Version: i.Version, + Version: p.Version, Qualifiers: purl.QualifiersFromMap(map[string]string{ purl.Type: m.Type, purl.Classifier: m.Classifier, @@ -231,7 +231,7 @@ func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { } // Ecosystem returns the OSV ecosystem ('Maven') of the software extracted by this extractor. -func (e Extractor) Ecosystem(i *extractor.Inventory) string { +func (e Extractor) Ecosystem(p *extractor.Package) string { return "Maven" } diff --git a/extractor/filesystem/language/java/pomxml/pomxml_test.go b/extractor/filesystem/language/java/pomxml/pomxml_test.go index f1a37136..d3be42b0 100644 --- a/extractor/filesystem/language/java/pomxml/pomxml_test.go +++ b/extractor/filesystem/language/java/pomxml/pomxml_test.go @@ -75,30 +75,30 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/not-pom.txt", }, - WantInventory: nil, - WantErr: extracttest.ContainsErrStr{Str: "could not extract from"}, + WantPackages: nil, + WantErr: extracttest.ContainsErrStr{Str: "could not extract from"}, }, { Name: "invalid syntax", InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/invalid-syntax.xml", }, - WantInventory: nil, - WantErr: extracttest.ContainsErrStr{Str: "could not extract from"}, + WantPackages: nil, + WantErr: extracttest.ContainsErrStr{Str: "could not extract from"}, }, { Name: "no packages", InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/empty.xml", }, - WantInventory: []*extractor.Inventory{}, + WantPackages: []*extractor.Package{}, }, { Name: "one package", InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/one-package.xml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "org.apache.maven:maven-artifact", Version: "1.0.0", @@ -116,7 +116,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/two-packages.xml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "io.netty:netty-all", Version: "4.1.42.Final", @@ -144,7 +144,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/with-dependency-management.xml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "io.netty:netty-all", Version: "4.1.9", @@ -182,7 +182,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/interpolation.xml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "org.mine:mypackage", Version: "1.0.0", @@ -220,7 +220,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/with-scope.xml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "abc:xyz", Version: "1.2.3", @@ -248,7 +248,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/with-type-classifier.xml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "abc:xyz", Version: "1.0.0", @@ -279,7 +279,7 @@ func TestExtractor_Extract(t *testing.T) { return } - if diff := cmp.Diff(tt.WantInventory, got, cmpopts.SortSlices(extracttest.InventoryCmpLess)); diff != "" { + if diff := cmp.Diff(tt.WantPackages, got, cmpopts.SortSlices(extracttest.PackageCmpLess)); diff != "" { t.Errorf("%s.Extract(%q) diff (-want +got):\n%s", extr.Name(), tt.InputConfig.Path, diff) } }) diff --git a/extractor/filesystem/language/java/pomxmlnet/pomxmlnet.go b/extractor/filesystem/language/java/pomxmlnet/pomxmlnet.go index 7b03a289..66d008c6 100644 --- a/extractor/filesystem/language/java/pomxmlnet/pomxmlnet.go +++ b/extractor/filesystem/language/java/pomxmlnet/pomxmlnet.go @@ -103,7 +103,7 @@ func (e Extractor) FileRequired(fapi filesystem.FileAPI) bool { } // Extract extracts packages from pom.xml files passed through the scan input. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { var project maven.Project if err := datasource.NewMavenDecoder(input.Reader).Decode(&project); err != nil { return nil, fmt.Errorf("could not extract from %s: %w", input.Path, err) @@ -198,12 +198,12 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] g.Edges[i] = e } - details := map[string]*extractor.Inventory{} + details := map[string]*extractor.Package{} for i := 1; i < len(g.Nodes); i++ { // Ignore the first node which is the root. node := g.Nodes[i] depGroups := []string{} - inventory := extractor.Inventory{ + pkg := extractor.Package{ Name: node.Version.Name, Version: node.Version.Version, // TODO(#408): Add merged paths in here as well @@ -213,36 +213,36 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] // not transitive dependencies because the nodes in the resolve graph does // not have the scope information. for _, dep := range project.Dependencies { - if dep.Name() != inventory.Name { + if dep.Name() != pkg.Name { continue } if dep.Scope != "" && dep.Scope != "compile" { depGroups = append(depGroups, string(dep.Scope)) } } - inventory.Metadata = osv.DepGroupMetadata{ + pkg.Metadata = osv.DepGroupMetadata{ DepGroupVals: depGroups, } - details[inventory.Name] = &inventory + details[pkg.Name] = &pkg } return maps.Values(details), nil } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { - g, a, _ := strings.Cut(i.Name, ":") +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { + g, a, _ := strings.Cut(p.Name, ":") return &purl.PackageURL{ Type: purl.TypeMaven, Namespace: g, Name: a, - Version: i.Version, + Version: p.Version, // TODO(#426): add Maven classifier and type to PURL. } } // Ecosystem returns the OSV ecosystem ('npm') of the software extracted by this extractor. -func (e Extractor) Ecosystem(_ *extractor.Inventory) string { +func (e Extractor) Ecosystem(_ *extractor.Package) string { return "Maven" } diff --git a/extractor/filesystem/language/java/pomxmlnet/pomxmlnet_test.go b/extractor/filesystem/language/java/pomxmlnet/pomxmlnet_test.go index d74a88e1..84f4d356 100644 --- a/extractor/filesystem/language/java/pomxmlnet/pomxmlnet_test.go +++ b/extractor/filesystem/language/java/pomxmlnet/pomxmlnet_test.go @@ -91,14 +91,14 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/maven/empty.xml", }, - WantInventory: []*extractor.Inventory{}, + WantPackages: []*extractor.Package{}, }, { Name: "one package", InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/maven/one-package.xml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "org.apache.maven:maven-artifact", Version: "1.0.0", @@ -112,7 +112,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/maven/two-packages.xml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "io.netty:netty-all", Version: "4.1.42.Final", @@ -132,7 +132,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/maven/with-dependency-management.xml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "io.netty:netty-all", Version: "4.1.9", @@ -152,7 +152,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/maven/interpolation.xml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "org.mine:mypackage", Version: "1.0.0", @@ -178,7 +178,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/maven/with-scope.xml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "junit:junit", Version: "4.12", @@ -192,7 +192,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/maven/transitive.xml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "org.direct:alice", Version: "1.0.0", @@ -257,7 +257,7 @@ func TestExtractor_Extract(t *testing.T) { return } - if diff := cmp.Diff(tt.WantInventory, got, cmpopts.SortSlices(extracttest.InventoryCmpLess)); diff != "" { + if diff := cmp.Diff(tt.WantPackages, got, cmpopts.SortSlices(extracttest.PackageCmpLess)); diff != "" { t.Errorf("%s.Extract(%q) diff (-want +got):\n%s", extr.Name(), tt.InputConfig.Path, diff) } }) @@ -270,7 +270,7 @@ func TestExtractor_Extract_WithMockServer(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/maven/with-parent.xml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "org.alice:alice", Version: "1.0.0", @@ -365,7 +365,7 @@ func TestExtractor_Extract_WithMockServer(t *testing.T) { return } - if diff := cmp.Diff(tt.WantInventory, got, cmpopts.SortSlices(extracttest.InventoryCmpLess)); diff != "" { + if diff := cmp.Diff(tt.WantPackages, got, cmpopts.SortSlices(extracttest.PackageCmpLess)); diff != "" { t.Errorf("%s.Extract(%q) diff (-want +got):\n%s", extr.Name(), tt.InputConfig.Path, diff) } } diff --git a/extractor/filesystem/language/javascript/bunlock/bunlock.go b/extractor/filesystem/language/javascript/bunlock/bunlock.go index c4d904e3..db035f12 100644 --- a/extractor/filesystem/language/javascript/bunlock/bunlock.go +++ b/extractor/filesystem/language/javascript/bunlock/bunlock.go @@ -79,12 +79,12 @@ func (e Extractor) FileRequired(api filesystem.FileAPI) bool { // structurePackageDetails returns the name, version, and commit of a package // specified as a tuple in a bun.lock -func structurePackageDetails(pkg []any) (string, string, string, error) { - if len(pkg) == 0 { +func structurePackageDetails(pkgs []any) (string, string, string, error) { + if len(pkgs) == 0 { return "", "", "", fmt.Errorf("empty package tuple") } - str, ok := pkg[0].(string) + str, ok := pkgs[0].(string) if !ok { return "", "", "", fmt.Errorf("first element of package tuple is not a string") @@ -114,7 +114,7 @@ func structurePackageDetails(pkg []any) (string, string, string, error) { } // Extract extracts packages from bun.lock files passed through the scan input. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { var parsedLockfile *bunLockfile b, err := io.ReadAll(input.Reader) @@ -127,7 +127,7 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] return nil, fmt.Errorf("could not extract from %q: %w", input.Path, err) } - inventories := make([]*extractor.Inventory, 0, len(parsedLockfile.Packages)) + packages := make([]*extractor.Package, 0, len(parsedLockfile.Packages)) var errs []error @@ -140,7 +140,7 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] continue } - inventories = append(inventories, &extractor.Inventory{ + packages = append(packages, &extractor.Package{ Name: name, Version: version, SourceCode: &extractor.SourceCodeIdentifier{ @@ -153,17 +153,17 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] }) } - return inventories, errors.Join(errs...) + return packages, errors.Join(errs...) } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { return &purl.PackageURL{ Type: purl.TypeNPM, - Name: strings.ToLower(i.Name), - Version: i.Version, + Name: strings.ToLower(p.Name), + Version: p.Version, } } // Ecosystem returns the OSV ecosystem ('npm') of the software extracted by this extractor. -func (e Extractor) Ecosystem(_ *extractor.Inventory) string { return "npm" } +func (e Extractor) Ecosystem(_ *extractor.Package) string { return "npm" } diff --git a/extractor/filesystem/language/javascript/bunlock/bunlock_test.go b/extractor/filesystem/language/javascript/bunlock/bunlock_test.go index ecf3a405..665f64e2 100644 --- a/extractor/filesystem/language/javascript/bunlock/bunlock_test.go +++ b/extractor/filesystem/language/javascript/bunlock/bunlock_test.go @@ -87,29 +87,29 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/not-json.txt", }, - WantErr: extracttest.ContainsErrStr{Str: "could not extract from"}, - WantInventory: nil, + WantErr: extracttest.ContainsErrStr{Str: "could not extract from"}, + WantPackages: nil, }, { Name: "empty", InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/empty.json5", }, - WantInventory: []*extractor.Inventory{}, + WantPackages: []*extractor.Package{}, }, { Name: "no packages", InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/no-packages.json5", }, - WantInventory: []*extractor.Inventory{}, + WantPackages: []*extractor.Package{}, }, { Name: "one package", InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/one-package.json5", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "wrappy", Version: "1.0.2", @@ -126,7 +126,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/one-package-dev.json5", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "wrappy", Version: "1.0.2", @@ -144,7 +144,7 @@ func TestExtractor_Extract(t *testing.T) { Path: "testdata/bad-tuple.json5", }, WantErr: extracttest.ContainsErrStr{Str: "could not extract 'wrappy-bad1' from"}, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "wrappy", Version: "1.0.2", @@ -162,7 +162,7 @@ func TestExtractor_Extract(t *testing.T) { Path: "testdata/bad-tuple.json5", }, WantErr: extracttest.ContainsErrStr{Str: "could not extract 'wrappy-bad2' from"}, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "wrappy", Version: "1.0.2", @@ -179,7 +179,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/two-packages.json5", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "has-flag", Version: "4.0.0", @@ -205,7 +205,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/same-package-different-groups.json5", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "has-flag", Version: "3.0.0", @@ -231,7 +231,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/scoped-packages.json5", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "@typescript-eslint/types", Version: "5.62.0", @@ -248,7 +248,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/scoped-packages-mixed.json5", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "@babel/code-frame", Version: "7.26.2", @@ -301,7 +301,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/optional-package.json5", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "acorn", Version: "8.14.0", @@ -336,7 +336,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/peer-dependencies-implicit.json5", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "acorn-jsx", Version: "5.3.2", @@ -362,7 +362,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/peer-dependencies-explicit.json5", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "acorn-jsx", Version: "5.3.2", @@ -388,7 +388,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/nested-dependencies.json5", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "ansi-styles", Version: "4.3.0", @@ -477,7 +477,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/nested-dependencies-dup.json5", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "ansi-styles", Version: "4.3.0", @@ -548,7 +548,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/alias.json5", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "has-flag", Version: "4.0.0", @@ -592,7 +592,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/commits.json5", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "@babel/helper-plugin-utils", Version: "7.26.5", @@ -776,7 +776,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/files.json5", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "etag", Version: "", @@ -802,7 +802,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/blog-sample.json5", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "uWebSockets.js", Version: "", @@ -832,7 +832,7 @@ func TestExtractor_Extract(t *testing.T) { return } - if diff := cmp.Diff(tt.WantInventory, got, cmpopts.SortSlices(extracttest.InventoryCmpLess)); diff != "" { + if diff := cmp.Diff(tt.WantPackages, got, cmpopts.SortSlices(extracttest.PackageCmpLess)); diff != "" { t.Errorf("%s.Extract(%q) diff (-want +got):\n%s", extr.Name(), tt.InputConfig.Path, diff) } }) diff --git a/extractor/filesystem/language/javascript/packagejson/packagejson.go b/extractor/filesystem/language/javascript/packagejson/packagejson.go index 46a2a425..a07463bf 100644 --- a/extractor/filesystem/language/javascript/packagejson/packagejson.go +++ b/extractor/filesystem/language/javascript/packagejson/packagejson.go @@ -139,21 +139,21 @@ func (e Extractor) reportFileRequired(path string, fileSizeBytes int64, result s } // Extract extracts packages from package.json files passed through the scan input. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { - i, err := parse(input.Path, input.Reader) +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { + p, err := parse(input.Path, input.Reader) if err != nil { e.reportFileExtracted(input.Path, input.Info, err) return nil, fmt.Errorf("packagejson.parse(%s): %w", input.Path, err) } - inventory := []*extractor.Inventory{} - if i != nil { - inventory = append(inventory, i) - i.Locations = []string{input.Path} + pkgs := []*extractor.Package{} + if p != nil { + pkgs = append(pkgs, p) + p.Locations = []string{input.Path} } e.reportFileExtracted(input.Path, input.Info, nil) - return inventory, nil + return pkgs, nil } func (e Extractor) reportFileExtracted(path string, fileinfo fs.FileInfo, err error) { @@ -171,7 +171,7 @@ func (e Extractor) reportFileExtracted(path string, fileinfo fs.FileInfo, err er }) } -func parse(path string, r io.Reader) (*extractor.Inventory, error) { +func parse(path string, r io.Reader) (*extractor.Package, error) { dec := json.NewDecoder(r) var p packageJSON @@ -194,7 +194,7 @@ func parse(path string, r io.Reader) (*extractor.Inventory, error) { return nil, nil } - return &extractor.Inventory{ + return &extractor.Package{ Name: p.Name, Version: p.Version, Metadata: &JavascriptPackageJSONMetadata{ @@ -214,7 +214,7 @@ func (p packageJSON) hasNameAndVersionValues() bool { // Visual Studio Code uses package.lock files as manifest files for extensions: // https://code.visualstudio.com/api/references/extension-manifest // These files are similar to NPM package.lock: -// https://docs.npmjs.com/cli/v10/configuring-npm/package-json +// https://docs.npmjs.com/cli/v10/configuring-npm/package.jsonn // The `engine` field exists in both but is required to contain `vscode` in the extension. // The `contributes` field is not required but only exists for VSCode extensions. func (p packageJSON) isVSCodeExtension() bool { @@ -247,16 +247,16 @@ func removeEmptyPersons(persons []*Person) []*Person { return result } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { return &purl.PackageURL{ Type: purl.TypeNPM, - Name: strings.ToLower(i.Name), - Version: i.Version, + Name: strings.ToLower(p.Name), + Version: p.Version, } } // Ecosystem returns the OSV Ecosystem of the software extracted by this extractor. // OSV requires the name field to be a npm package. This is a javascript extractor, there is no // guarantee that the package is an npm package. -func (Extractor) Ecosystem(i *extractor.Inventory) string { return "npm" } +func (Extractor) Ecosystem(p *extractor.Package) string { return "npm" } diff --git a/extractor/filesystem/language/javascript/packagejson/packagejson_test.go b/extractor/filesystem/language/javascript/packagejson/packagejson_test.go index b48343dc..2d80f96c 100644 --- a/extractor/filesystem/language/javascript/packagejson/packagejson_test.go +++ b/extractor/filesystem/language/javascript/packagejson/packagejson_test.go @@ -138,14 +138,14 @@ func TestExtract(t *testing.T) { name string path string cfg packagejson.Config - wantInventory []*extractor.Inventory + wantPackages []*extractor.Package wantErr error wantResultMetric stats.FileExtractedResult }{ { name: "top level package.json", path: "testdata/package.json", - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "testdata", Version: "10.46.8", @@ -163,7 +163,7 @@ func TestExtract(t *testing.T) { { name: "accepts", path: "testdata/deps/accepts/package.json", - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "accepts", Version: "1.3.8", @@ -187,7 +187,7 @@ func TestExtract(t *testing.T) { { name: "no person name", path: "testdata/deps/no-person-name/package.json", - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "accepts", Version: "1.3.8", @@ -207,7 +207,7 @@ func TestExtract(t *testing.T) { { name: "nested acorn", path: "testdata/deps/with/deps/acorn/package.json", - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "acorn", Version: "1.2.2", @@ -228,39 +228,39 @@ func TestExtract(t *testing.T) { }, }, { - name: "empty name", - path: "testdata/deps/acorn/package.json", - wantInventory: []*extractor.Inventory{}, + name: "empty name", + path: "testdata/deps/acorn/package.json", + wantPackages: []*extractor.Package{}, }, { - name: "empty version", - path: "testdata/deps/acorn-globals/package.json", - wantInventory: []*extractor.Inventory{}, + name: "empty version", + path: "testdata/deps/acorn-globals/package.json", + wantPackages: []*extractor.Package{}, }, { - name: "missing name and version", - path: "testdata/deps/window-size/package.json", - wantInventory: []*extractor.Inventory{}, + name: "missing name and version", + path: "testdata/deps/window-size/package.json", + wantPackages: []*extractor.Package{}, }, { - name: "VSCode extension", - path: "testdata/vscode-extension.json", - wantInventory: []*extractor.Inventory{}, + name: "VSCode extension", + path: "testdata/vscode-extension.json", + wantPackages: []*extractor.Package{}, }, { - name: "VSCode extension with only required fields", - path: "testdata/vscode-extension-only-required.json", - wantInventory: []*extractor.Inventory{}, + name: "VSCode extension with only required fields", + path: "testdata/vscode-extension-only-required.json", + wantPackages: []*extractor.Package{}, }, { - name: "Unity package", - path: "testdata/unity-package.json", - wantInventory: []*extractor.Inventory{}, + name: "Unity package", + path: "testdata/unity-package.json", + wantPackages: []*extractor.Package{}, }, { name: "Undici package with nonstandard contributors parsed correctly", path: "testdata/undici-package.json", - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "undici", Version: "5.28.3", @@ -288,7 +288,7 @@ func TestExtract(t *testing.T) { { name: "npm package with engine field set", path: "testdata/not-vscode.json", - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "jsonparse", Version: "1.3.1", @@ -343,9 +343,9 @@ func TestExtract(t *testing.T) { t.Fatalf("Extract(%+v) error: got %v, want %v\n", tt.name, err, tt.wantErr) } - var want []*extractor.Inventory - if tt.wantInventory != nil { - want = tt.wantInventory + var want []*extractor.Package + if tt.wantPackages != nil { + want = tt.wantPackages } if diff := cmp.Diff(want, got); diff != "" { @@ -384,7 +384,7 @@ func defaultConfigWith(cfg packagejson.Config) packagejson.Config { func TestToPURL(t *testing.T) { e := packagejson.Extractor{} - i := &extractor.Inventory{ + p := &extractor.Package{ Name: "Name", Version: "1.2.3", Locations: []string{"location"}, @@ -394,8 +394,8 @@ func TestToPURL(t *testing.T) { Name: "name", Version: "1.2.3", } - got := e.ToPURL(i) + got := e.ToPURL(p) if diff := cmp.Diff(want, got); diff != "" { - t.Errorf("ToPURL(%v) (-want +got):\n%s", i, diff) + t.Errorf("ToPURL(%v) (-want +got):\n%s", p, diff) } } diff --git a/extractor/filesystem/language/javascript/packagelockjson/packagelockjson-v1_test.go b/extractor/filesystem/language/javascript/packagelockjson/packagelockjson-v1_test.go index 0fca59d3..cd446d20 100644 --- a/extractor/filesystem/language/javascript/packagelockjson/packagelockjson-v1_test.go +++ b/extractor/filesystem/language/javascript/packagelockjson/packagelockjson-v1_test.go @@ -42,14 +42,14 @@ func TestNPMLockExtractor_Extract_V1(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/empty.v1.json", }, - WantInventory: []*extractor.Inventory{}, + WantPackages: []*extractor.Package{}, }, { Name: "one package", InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/one-package.v1.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "wrappy", Version: "1.0.2", @@ -66,7 +66,7 @@ func TestNPMLockExtractor_Extract_V1(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/one-package-dev.v1.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "wrappy", Version: "1.0.2", @@ -83,7 +83,7 @@ func TestNPMLockExtractor_Extract_V1(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/two-packages.v1.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "wrappy", Version: "1.0.2", @@ -109,7 +109,7 @@ func TestNPMLockExtractor_Extract_V1(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/scoped-packages.v1.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "wrappy", Version: "1.0.2", @@ -135,7 +135,7 @@ func TestNPMLockExtractor_Extract_V1(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/nested-dependencies.v1.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "postcss", Version: "6.0.23", @@ -188,7 +188,7 @@ func TestNPMLockExtractor_Extract_V1(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/nested-dependencies-dup.v1.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "supports-color", Version: "2.0.0", @@ -547,7 +547,7 @@ func TestNPMLockExtractor_Extract_V1(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/commits.v1.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "@segment/analytics.js-integration-facebook-pixel", Version: "", @@ -716,7 +716,7 @@ func TestNPMLockExtractor_Extract_V1(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/files.v1.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "lodash", Version: "1.3.1", @@ -742,7 +742,7 @@ func TestNPMLockExtractor_Extract_V1(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/alias.v1.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "@babel/code-frame", Version: "7.0.0", @@ -777,7 +777,7 @@ func TestNPMLockExtractor_Extract_V1(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/optional-package.v1.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "wrappy", Version: "1.0.2", @@ -803,7 +803,7 @@ func TestNPMLockExtractor_Extract_V1(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/same-package-different-groups.v1.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "eslint", Version: "1.2.3", @@ -852,7 +852,7 @@ func TestNPMLockExtractor_Extract_V1(t *testing.T) { return } - if diff := cmp.Diff(tt.WantInventory, got, cmpopts.SortSlices(extracttest.InventoryCmpLess)); diff != "" { + if diff := cmp.Diff(tt.WantPackages, got, cmpopts.SortSlices(extracttest.PackageCmpLess)); diff != "" { t.Errorf("%s.Extract(%q) diff (-want +got):\n%s", extr.Name(), tt.InputConfig.Path, diff) } diff --git a/extractor/filesystem/language/javascript/packagelockjson/packagelockjson-v2_test.go b/extractor/filesystem/language/javascript/packagelockjson/packagelockjson-v2_test.go index ce06d9c0..c0a4ce4a 100644 --- a/extractor/filesystem/language/javascript/packagelockjson/packagelockjson-v2_test.go +++ b/extractor/filesystem/language/javascript/packagelockjson/packagelockjson-v2_test.go @@ -41,14 +41,14 @@ func TestNPMLockExtractor_Extract_V2(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/empty.v2.json", }, - WantInventory: []*extractor.Inventory{}, + WantPackages: []*extractor.Package{}, }, { Name: "one package", InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/one-package.v2.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "wrappy", Version: "1.0.2", @@ -67,7 +67,7 @@ func TestNPMLockExtractor_Extract_V2(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/one-package-dev.v2.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "wrappy", Version: "1.0.2", @@ -86,7 +86,7 @@ func TestNPMLockExtractor_Extract_V2(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/two-packages.v2.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "wrappy", Version: "1.0.2", @@ -116,7 +116,7 @@ func TestNPMLockExtractor_Extract_V2(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/scoped-packages.v2.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "wrappy", Version: "1.0.2", @@ -146,7 +146,7 @@ func TestNPMLockExtractor_Extract_V2(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/nested-dependencies.v2.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "postcss", Version: "6.0.23", @@ -209,7 +209,7 @@ func TestNPMLockExtractor_Extract_V2(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/nested-dependencies-dup.v2.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "supports-color", Version: "6.1.0", @@ -239,7 +239,7 @@ func TestNPMLockExtractor_Extract_V2(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/commits.v2.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "@segment/analytics.js-integration-facebook-pixel", Version: "2.4.1", @@ -401,7 +401,7 @@ func TestNPMLockExtractor_Extract_V2(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/files.v2.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "etag", Version: "1.8.0", @@ -442,7 +442,7 @@ func TestNPMLockExtractor_Extract_V2(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/alias.v2.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "@babel/code-frame", Version: "7.0.0", @@ -483,7 +483,7 @@ func TestNPMLockExtractor_Extract_V2(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/optional-package.v2.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "wrappy", Version: "1.0.2", @@ -513,7 +513,7 @@ func TestNPMLockExtractor_Extract_V2(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/same-package-different-groups.v2.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "eslint", Version: "1.2.3", @@ -568,7 +568,7 @@ func TestNPMLockExtractor_Extract_V2(t *testing.T) { return } - if diff := cmp.Diff(tt.WantInventory, got, cmpopts.SortSlices(extracttest.InventoryCmpLess)); diff != "" { + if diff := cmp.Diff(tt.WantPackages, got, cmpopts.SortSlices(extracttest.PackageCmpLess)); diff != "" { t.Errorf("%s.Extract(%q) diff (-want +got):\n%s", extr.Name(), tt.InputConfig.Path, diff) } diff --git a/extractor/filesystem/language/javascript/packagelockjson/packagelockjson.go b/extractor/filesystem/language/javascript/packagelockjson/packagelockjson.go index 7d8b196e..e0487f24 100644 --- a/extractor/filesystem/language/javascript/packagelockjson/packagelockjson.go +++ b/extractor/filesystem/language/javascript/packagelockjson/packagelockjson.go @@ -273,8 +273,8 @@ func (e Extractor) reportFileRequired(path string, fileSizeBytes int64, result s } // Extract extracts packages from package-lock.json files passed through the scan input. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { - inventories, err := e.extractPkgLock(ctx, input) +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { + packages, err := e.extractPackageLock(ctx, input) if e.stats != nil { var fileSizeBytes int64 @@ -288,10 +288,10 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] }) } - return inventories, err + return packages, err } -func (e Extractor) extractPkgLock(_ context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) extractPackageLock(_ context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { var parsedLockfile *packagelockjson.LockFile err := json.NewDecoder(input.Reader).Decode(&parsedLockfile) @@ -301,14 +301,14 @@ func (e Extractor) extractPkgLock(_ context.Context, input *filesystem.ScanInput } packages := maps.Values(parseNpmLock(*parsedLockfile)) - inventories := make([]*extractor.Inventory, len(packages)) + result := make([]*extractor.Package, len(packages)) for i, pkg := range packages { if pkg.DepGroups == nil { pkg.DepGroups = []string{} } - inventories[i] = &extractor.Inventory{ + result[i] = &extractor.Package{ Name: pkg.Name, SourceCode: &extractor.SourceCodeIdentifier{ Commit: pkg.Commit, @@ -321,17 +321,17 @@ func (e Extractor) extractPkgLock(_ context.Context, input *filesystem.ScanInput } } - return inventories, nil + return result, nil } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { return &purl.PackageURL{ Type: purl.TypeNPM, - Name: strings.ToLower(i.Name), - Version: i.Version, + Name: strings.ToLower(p.Name), + Version: p.Version, } } // Ecosystem returns the OSV ecosystem ('npm') of the software extracted by this extractor. -func (e Extractor) Ecosystem(_ *extractor.Inventory) string { return "npm" } +func (e Extractor) Ecosystem(_ *extractor.Package) string { return "npm" } diff --git a/extractor/filesystem/language/javascript/packagelockjson/packagelockjson_test.go b/extractor/filesystem/language/javascript/packagelockjson/packagelockjson_test.go index 47c741f3..07e19fe5 100644 --- a/extractor/filesystem/language/javascript/packagelockjson/packagelockjson_test.go +++ b/extractor/filesystem/language/javascript/packagelockjson/packagelockjson_test.go @@ -70,8 +70,8 @@ func TestExtractor_FileRequired(t *testing.T) { wantRequired: false, }, { - name: "path.to.my.package-lock.json", - path: filepath.FromSlash("path.to.my.package-lock.json"), + name: "path.to.my.package.lock.json", + path: filepath.FromSlash("path.to.my.package.lock.json"), wantRequired: false, }, { @@ -148,7 +148,7 @@ func TestExtractor_FileRequired(t *testing.T) { func TestToPURL(t *testing.T) { e := packagelockjson.Extractor{} - i := &extractor.Inventory{ + p := &extractor.Package{ Name: "Name", Version: "1.2.3", Locations: []string{"location"}, @@ -158,9 +158,9 @@ func TestToPURL(t *testing.T) { Name: "name", Version: "1.2.3", } - got := e.ToPURL(i) + got := e.ToPURL(p) if diff := cmp.Diff(want, got); diff != "" { - t.Errorf("ToPURL(%v) (-want +got):\n%s", i, diff) + t.Errorf("ToPURL(%v) (-want +got):\n%s", p, diff) } } diff --git a/extractor/filesystem/language/javascript/pnpmlock/pnpmlock-v9_test.go b/extractor/filesystem/language/javascript/pnpmlock/pnpmlock-v9_test.go index 5644305d..24b7bb90 100644 --- a/extractor/filesystem/language/javascript/pnpmlock/pnpmlock-v9_test.go +++ b/extractor/filesystem/language/javascript/pnpmlock/pnpmlock-v9_test.go @@ -33,14 +33,14 @@ func TestExtractor_Extract_v9(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/no-packages.v9.yaml", }, - WantInventory: []*extractor.Inventory{}, + WantPackages: []*extractor.Package{}, }, { Name: "one package", InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/one-package.v9.yaml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "acorn", Version: "8.11.3", @@ -57,7 +57,7 @@ func TestExtractor_Extract_v9(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/one-package-dev.v9.yaml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "acorn", Version: "8.11.3", @@ -74,7 +74,7 @@ func TestExtractor_Extract_v9(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/scoped-packages.v9.yaml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "@typescript-eslint/types", Version: "5.62.0", @@ -91,7 +91,7 @@ func TestExtractor_Extract_v9(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/peer-dependencies.v9.yaml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "acorn-jsx", Version: "5.3.2", @@ -117,7 +117,7 @@ func TestExtractor_Extract_v9(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/peer-dependencies-advanced.v9.yaml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "@eslint-community/eslint-utils", Version: "4.4.0", @@ -242,7 +242,7 @@ func TestExtractor_Extract_v9(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/multiple-versions.v9.yaml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "uuid", Version: "8.0.0", @@ -277,7 +277,7 @@ func TestExtractor_Extract_v9(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/commits.v9.yaml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "ansi-regex", Version: "6.0.1", @@ -307,7 +307,7 @@ func TestExtractor_Extract_v9(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/mixed-groups.v9.yaml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "ansi-regex", Version: "5.0.1", @@ -353,7 +353,7 @@ func TestExtractor_Extract_v9(t *testing.T) { return } - if diff := cmp.Diff(tt.WantInventory, got, cmpopts.SortSlices(extracttest.InventoryCmpLess)); diff != "" { + if diff := cmp.Diff(tt.WantPackages, got, cmpopts.SortSlices(extracttest.PackageCmpLess)); diff != "" { t.Errorf("%s.Extract(%q) diff (-want +got):\n%s", extr.Name(), tt.InputConfig.Path, diff) } }) diff --git a/extractor/filesystem/language/javascript/pnpmlock/pnpmlock.go b/extractor/filesystem/language/javascript/pnpmlock/pnpmlock.go index 6a4eba94..074f9a6c 100644 --- a/extractor/filesystem/language/javascript/pnpmlock/pnpmlock.go +++ b/extractor/filesystem/language/javascript/pnpmlock/pnpmlock.go @@ -165,8 +165,8 @@ func parseNameAtVersion(value string) (name string, version string) { return matches[1], matches[2] } -func parsePnpmLock(lockfile pnpmLockfile) ([]*extractor.Inventory, error) { - packages := make([]*extractor.Inventory, 0, len(lockfile.Packages)) +func parsePnpmLock(lockfile pnpmLockfile) ([]*extractor.Package, error) { + packages := make([]*extractor.Package, 0, len(lockfile.Packages)) errs := []error{} for s, pkg := range lockfile.Packages { @@ -208,7 +208,7 @@ func parsePnpmLock(lockfile pnpmLockfile) ([]*extractor.Inventory, error) { depGroups = append(depGroups, "dev") } - packages = append(packages, &extractor.Inventory{ + packages = append(packages, &extractor.Package{ Name: name, Version: version, SourceCode: &extractor.SourceCodeIdentifier{ @@ -256,7 +256,7 @@ func (e Extractor) FileRequired(api filesystem.FileAPI) bool { } // Extract extracts packages from a pnpm-lock.yaml file passed through the scan input. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { var parsedLockfile *pnpmLockfile err := yaml.NewDecoder(input.Reader).Decode(&parsedLockfile) @@ -270,25 +270,25 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] parsedLockfile = &pnpmLockfile{} } - inventories, err := parsePnpmLock(*parsedLockfile) - for i := range inventories { - inventories[i].Locations = []string{input.Path} + packages, err := parsePnpmLock(*parsedLockfile) + for i := range packages { + packages[i].Locations = []string{input.Path} } - return inventories, err + return packages, err } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { return &purl.PackageURL{ Type: purl.TypeNPM, - Name: strings.ToLower(i.Name), - Version: i.Version, + Name: strings.ToLower(p.Name), + Version: p.Version, } } // Ecosystem returns the OSV Ecosystem of the software extracted by this extractor. -func (e Extractor) Ecosystem(i *extractor.Inventory) string { +func (e Extractor) Ecosystem(p *extractor.Package) string { return "npm" } diff --git a/extractor/filesystem/language/javascript/pnpmlock/pnpmlock_test.go b/extractor/filesystem/language/javascript/pnpmlock/pnpmlock_test.go index a9d73d8b..4adc503e 100644 --- a/extractor/filesystem/language/javascript/pnpmlock/pnpmlock_test.go +++ b/extractor/filesystem/language/javascript/pnpmlock/pnpmlock_test.go @@ -87,8 +87,8 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/not-yaml.txt", }, - WantErr: extracttest.ContainsErrStr{Str: "could not extract from"}, - WantInventory: nil, + WantErr: extracttest.ContainsErrStr{Str: "could not extract from"}, + WantPackages: nil, }, { Name: "invalid dep path", @@ -96,7 +96,7 @@ func TestExtractor_Extract(t *testing.T) { Path: "testdata/invalid-path.yaml", }, WantErr: extracttest.ContainsErrStr{Str: "invalid dependency path"}, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "acorn", Version: "8.7.0", @@ -114,7 +114,7 @@ func TestExtractor_Extract(t *testing.T) { Path: "testdata/invalid-paths.yaml", }, WantErr: extracttest.ContainsErrStr{Str: "invalid dependency path: invalidpath1"}, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "acorn", Version: "8.7.0", @@ -132,7 +132,7 @@ func TestExtractor_Extract(t *testing.T) { Path: "testdata/invalid-paths.yaml", }, WantErr: extracttest.ContainsErrStr{Str: "invalid dependency path: invalidpath2"}, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "acorn", Version: "8.7.0", @@ -149,21 +149,21 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/empty.yaml", }, - WantInventory: []*extractor.Inventory{}, + WantPackages: []*extractor.Package{}, }, { Name: "no packages", InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/no-packages.yaml", }, - WantInventory: []*extractor.Inventory{}, + WantPackages: []*extractor.Package{}, }, { Name: "one package", InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/one-package.yaml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "acorn", Version: "8.7.0", @@ -180,7 +180,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/one-package-v6-lockfile.yaml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "acorn", Version: "8.7.0", @@ -197,7 +197,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/one-package-dev.yaml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "acorn", Version: "8.7.0", @@ -214,7 +214,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/scoped-packages.yaml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "@typescript-eslint/types", Version: "5.13.0", @@ -231,7 +231,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/scoped-packages-v6-lockfile.yaml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "@typescript-eslint/types", Version: "5.57.1", @@ -248,7 +248,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/peer-dependencies.yaml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "acorn-jsx", Version: "5.3.2", @@ -274,7 +274,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/peer-dependencies-advanced.yaml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "@typescript-eslint/eslint-plugin", Version: "5.13.0", @@ -363,7 +363,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/multiple-packages.yaml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "aws-sdk", Version: "2.1087.0", @@ -497,7 +497,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/multiple-versions.yaml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "uuid", Version: "3.3.2", @@ -532,7 +532,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/tarball.yaml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "@my-org/my-package", Version: "3.2.3", @@ -549,7 +549,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/exotic.yaml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "foo", Version: "1.0.0", @@ -620,7 +620,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/commits.yaml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "my-bitbucket-package", Version: "1.0.0", @@ -683,7 +683,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/files.yaml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "my-file-package", Version: "0.0.0", @@ -747,7 +747,7 @@ func TestExtractor_Extract(t *testing.T) { return } - if diff := cmp.Diff(tt.WantInventory, got, cmpopts.SortSlices(extracttest.InventoryCmpLess)); diff != "" { + if diff := cmp.Diff(tt.WantPackages, got, cmpopts.SortSlices(extracttest.PackageCmpLess)); diff != "" { t.Errorf("%s.Extract(%q) diff (-want +got):\n%s", extr.Name(), tt.InputConfig.Path, diff) } }) diff --git a/extractor/filesystem/language/javascript/yarnlock/yarnlock-v1_test.go b/extractor/filesystem/language/javascript/yarnlock/yarnlock-v1_test.go index 632786da..d8c8b868 100644 --- a/extractor/filesystem/language/javascript/yarnlock/yarnlock-v1_test.go +++ b/extractor/filesystem/language/javascript/yarnlock/yarnlock-v1_test.go @@ -32,14 +32,14 @@ func TestExtractor_Extract_v1(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/empty.v1.lock", }, - WantInventory: []*extractor.Inventory{}, + WantPackages: []*extractor.Package{}, }, { Name: "one package", InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/one-package.v1.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "balanced-match", Version: "1.0.2", @@ -55,7 +55,7 @@ func TestExtractor_Extract_v1(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/no-version.v1.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "balanced-match", Version: "1.0.2", @@ -71,7 +71,7 @@ func TestExtractor_Extract_v1(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/two-packages.v1.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "concat-stream", Version: "1.6.2", @@ -95,7 +95,7 @@ func TestExtractor_Extract_v1(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/with-quotes.v1.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "concat-stream", Version: "1.6.2", @@ -119,7 +119,7 @@ func TestExtractor_Extract_v1(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/multiple-versions.v1.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "define-properties", Version: "1.1.3", @@ -159,7 +159,7 @@ func TestExtractor_Extract_v1(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/multiple-constraints.v1.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "@babel/code-frame", Version: "7.12.13", @@ -183,7 +183,7 @@ func TestExtractor_Extract_v1(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/scoped-packages.v1.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "@babel/code-frame", Version: "7.12.11", @@ -207,7 +207,7 @@ func TestExtractor_Extract_v1(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/with-prerelease.v1.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "css-tree", Version: "1.0.0-alpha.37", @@ -255,7 +255,7 @@ func TestExtractor_Extract_v1(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/with-build-string.v1.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "domino", Version: "2.1.6+git", @@ -279,7 +279,7 @@ func TestExtractor_Extract_v1(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/commits.v1.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "mine1", Version: "1.0.0-alpha.37", @@ -431,7 +431,7 @@ func TestExtractor_Extract_v1(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/files.v1.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "etag", Version: "1.8.1", @@ -487,7 +487,7 @@ func TestExtractor_Extract_v1(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/with-aliases.v1.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "@babel/helper-validator-identifier", Version: "7.22.20", @@ -530,7 +530,7 @@ func TestExtractor_Extract_v1(t *testing.T) { return } - if diff := cmp.Diff(tt.WantInventory, got, cmpopts.SortSlices(extracttest.InventoryCmpLess)); diff != "" { + if diff := cmp.Diff(tt.WantPackages, got, cmpopts.SortSlices(extracttest.PackageCmpLess)); diff != "" { t.Errorf("%s.Extract(%q) diff (-want +got):\n%s", extr.Name(), tt.InputConfig.Path, diff) } }) diff --git a/extractor/filesystem/language/javascript/yarnlock/yarnlock-v2_test.go b/extractor/filesystem/language/javascript/yarnlock/yarnlock-v2_test.go index 27a7199a..ca164828 100644 --- a/extractor/filesystem/language/javascript/yarnlock/yarnlock-v2_test.go +++ b/extractor/filesystem/language/javascript/yarnlock/yarnlock-v2_test.go @@ -32,14 +32,14 @@ func TestExtractor_Extract_v2(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/empty.v2.lock", }, - WantInventory: []*extractor.Inventory{}, + WantPackages: []*extractor.Package{}, }, { Name: "one package", InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/one-package.v2.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "balanced-match", Version: "1.0.2", @@ -55,7 +55,7 @@ func TestExtractor_Extract_v2(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/two-packages.v2.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "compare-func", Version: "2.0.0", @@ -79,7 +79,7 @@ func TestExtractor_Extract_v2(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/with-quotes.v2.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "compare-func", Version: "2.0.0", @@ -103,7 +103,7 @@ func TestExtractor_Extract_v2(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/multiple-versions.v2.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "debug", Version: "4.3.3", @@ -135,7 +135,7 @@ func TestExtractor_Extract_v2(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/scoped-packages.v2.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "@babel/cli", Version: "7.16.8", @@ -167,7 +167,7 @@ func TestExtractor_Extract_v2(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/with-prerelease.v2.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "@nicolo-ribaudo/chokidar-2", Version: "2.1.8-no-fsevents.3", @@ -199,7 +199,7 @@ func TestExtractor_Extract_v2(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/with-build-string.v2.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "domino", Version: "2.1.6+git", @@ -231,7 +231,7 @@ func TestExtractor_Extract_v2(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/commits.v2.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "@my-scope/my-first-package", Version: "0.0.6", @@ -295,7 +295,7 @@ func TestExtractor_Extract_v2(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/files.v2.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "my-package", Version: "0.0.2", @@ -311,7 +311,7 @@ func TestExtractor_Extract_v2(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/with-aliases.v2.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "@babel/helper-validator-identifier", Version: "7.22.20", @@ -362,7 +362,7 @@ func TestExtractor_Extract_v2(t *testing.T) { return } - if diff := cmp.Diff(tt.WantInventory, got, cmpopts.SortSlices(extracttest.InventoryCmpLess)); diff != "" { + if diff := cmp.Diff(tt.WantPackages, got, cmpopts.SortSlices(extracttest.PackageCmpLess)); diff != "" { t.Errorf("%s.Extract(%q) diff (-want +got):\n%s", extr.Name(), tt.InputConfig.Path, diff) } }) diff --git a/extractor/filesystem/language/javascript/yarnlock/yarnlock.go b/extractor/filesystem/language/javascript/yarnlock/yarnlock.go index c1ef42df..56e46194 100644 --- a/extractor/filesystem/language/javascript/yarnlock/yarnlock.go +++ b/extractor/filesystem/language/javascript/yarnlock/yarnlock.go @@ -44,7 +44,7 @@ var ( yarnPackageVersionRe = regexp.MustCompile(`^ {2}"?version"?:? "?([\w-.+]+)"?$`) // Package resolution matcher regex. Might contain commit hashes. // Format for yarn.lock v1: `resolved "git+ssh://git@github.com:G-Rath/repo-2#hash"` - // Format for yarn.lock v2: `resolution: "@my-scope/my-first-package@https://github.com/my-org/my-first-package.git#commit=hash"` + // Format for yarn.lock v2: `resolution: "@my-scope/my-first-package@https://github.com/my-org/my-first-pkg.git#commit=hash"` yarnPackageResolutionRe = regexp.MustCompile(`^ {2}"?(?:resolution:|resolved)"? "([^ '"]+)"$`) // Regexes for matching commit hashes in the resolution. commitMatchers = []*regexp.Regexp{ @@ -166,7 +166,7 @@ func determineYarnPackageResolution(props []string) string { return "" } -func parseYarnPackageGroup(desc *packageDescription) *extractor.Inventory { +func parseYarnPackageGroup(desc *packageDescription) *extractor.Package { name := extractYarnPackageName(desc.header) version := determineYarnPackageVersion(desc.props) resolution := determineYarnPackageResolution(desc.props) @@ -175,7 +175,7 @@ func parseYarnPackageGroup(desc *packageDescription) *extractor.Inventory { log.Errorf("Failed to determine version of %s while parsing a yarn.lock", name) } - return &extractor.Inventory{ + return &extractor.Package{ Name: name, Version: version, SourceCode: &extractor.SourceCodeIdentifier{ @@ -219,7 +219,7 @@ func (e Extractor) FileRequired(api filesystem.FileAPI) bool { } // Extract extracts packages from NPM yarn.lock files passed through the scan input. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { scanner := bufio.NewScanner(input.Reader) packageGroups, err := groupYarnPackageDescriptions(ctx, scanner) @@ -227,31 +227,31 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] return nil, fmt.Errorf("error while scanning %s: %w", input.Path, err) } - packages := make([]*extractor.Inventory, 0, len(packageGroups)) + packages := make([]*extractor.Package, 0, len(packageGroups)) for _, group := range packageGroups { if group.header == "__metadata:" { // This group doesn't describe a package. continue } - inv := parseYarnPackageGroup(group) - inv.Locations = []string{input.Path} - packages = append(packages, inv) + pkg := parseYarnPackageGroup(group) + pkg.Locations = []string{input.Path} + packages = append(packages, pkg) } return packages, nil } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { return &purl.PackageURL{ Type: purl.TypeNPM, - Name: i.Name, - Version: i.Version, + Name: p.Name, + Version: p.Version, } } // Ecosystem returns the OSV Ecosystem of the software extracted by this extractor. -func (e Extractor) Ecosystem(i *extractor.Inventory) string { return "npm" } +func (e Extractor) Ecosystem(p *extractor.Package) string { return "npm" } var _ filesystem.Extractor = Extractor{} diff --git a/extractor/filesystem/language/php/composerlock/composerlock.go b/extractor/filesystem/language/php/composerlock/composerlock.go index 1ffbc47c..109f9d21 100644 --- a/extractor/filesystem/language/php/composerlock/composerlock.go +++ b/extractor/filesystem/language/php/composerlock/composerlock.go @@ -69,7 +69,7 @@ func (e Extractor) FileRequired(api filesystem.FileAPI) bool { } // Extract extracts packages from a composer.lock file passed through the scan input. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { var parsedLockfile *composerLock err := json.NewDecoder(input.Reader).Decode(&parsedLockfile) @@ -79,14 +79,14 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] } packages := make( - []*extractor.Inventory, + []*extractor.Package, 0, // len cannot return negative numbers, but the types can't reflect that uint64(len(parsedLockfile.Packages))+uint64(len(parsedLockfile.PackagesDev)), ) for _, composerPackage := range parsedLockfile.Packages { - packages = append(packages, &extractor.Inventory{ + packages = append(packages, &extractor.Package{ Name: composerPackage.Name, Version: composerPackage.Version, Locations: []string{input.Path}, @@ -100,7 +100,7 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] } for _, composerPackage := range parsedLockfile.PackagesDev { - packages = append(packages, &extractor.Inventory{ + packages = append(packages, &extractor.Package{ Name: composerPackage.Name, Version: composerPackage.Version, Locations: []string{input.Path}, @@ -116,17 +116,17 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] return packages, nil } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { return &purl.PackageURL{ Type: purl.TypeComposer, - Name: i.Name, - Version: i.Version, + Name: p.Name, + Version: p.Version, } } // Ecosystem returns the OSV Ecosystem of the software extracted by this extractor. -func (e Extractor) Ecosystem(i *extractor.Inventory) string { +func (e Extractor) Ecosystem(p *extractor.Package) string { return "Packagist" } diff --git a/extractor/filesystem/language/php/composerlock/composerlock_test.go b/extractor/filesystem/language/php/composerlock/composerlock_test.go index 0f01f7ab..8ade9952 100644 --- a/extractor/filesystem/language/php/composerlock/composerlock_test.go +++ b/extractor/filesystem/language/php/composerlock/composerlock_test.go @@ -82,22 +82,22 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/not-json.txt", }, - WantInventory: nil, - WantErr: extracttest.ContainsErrStr{Str: "could not extract from"}, + WantPackages: nil, + WantErr: extracttest.ContainsErrStr{Str: "could not extract from"}, }, { Name: "no packages", InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/empty.json", }, - WantInventory: []*extractor.Inventory{}, + WantPackages: []*extractor.Package{}, }, { Name: "one package", InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/one-package.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "sentry/sdk", Version: "2.0.4", @@ -116,7 +116,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/one-package-dev.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "sentry/sdk", Version: "2.0.4", @@ -135,7 +135,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/two-packages.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "sentry/sdk", Version: "2.0.4", @@ -165,7 +165,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/two-packages-alt.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "sentry/sdk", Version: "2.0.4", @@ -206,7 +206,7 @@ func TestExtractor_Extract(t *testing.T) { return } - if diff := cmp.Diff(tt.WantInventory, got, cmpopts.SortSlices(extracttest.InventoryCmpLess)); diff != "" { + if diff := cmp.Diff(tt.WantPackages, got, cmpopts.SortSlices(extracttest.PackageCmpLess)); diff != "" { t.Errorf("%s.Extract(%q) diff (-want +got):\n%s", extr.Name(), tt.InputConfig.Path, diff) } }) diff --git a/extractor/filesystem/language/python/condameta/condameta.go b/extractor/filesystem/language/python/condameta/condameta.go index 9101a272..517bb93d 100644 --- a/extractor/filesystem/language/python/condameta/condameta.go +++ b/extractor/filesystem/language/python/condameta/condameta.go @@ -134,8 +134,8 @@ func (e Extractor) reportFileRequired(path string, fileSizeBytes int64, result s } // Extract parses and extracts dependency data from Conda metadata files. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { - inventory, err := e.extractFromInput(ctx, input) +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { + pkg, err := e.extractFromInput(ctx, input) if e.stats != nil { var fileSizeBytes int64 if input.Info != nil { @@ -147,10 +147,10 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] FileSizeBytes: fileSizeBytes, }) } - return inventory, err + return pkg, err } -func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { // Parse the metadata and get a package pkg, err := parse(input.Reader) if err != nil { @@ -162,15 +162,13 @@ func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanI return nil, fmt.Errorf("package name or version is empty") } - inventory := &extractor.Inventory{ + return []*extractor.Package{&extractor.Package{ Name: pkg.Name, Version: pkg.Version, Locations: []string{ input.Path, }, - } - - return []*extractor.Inventory{inventory}, nil + }}, nil } // parse reads a Conda metadata JSON file and extracts a package. @@ -187,10 +185,10 @@ type condaPackage struct { Version string `json:"version"` } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { - return pypipurl.MakePackageURL(i) +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { + return pypipurl.MakePackageURL(p) } // Ecosystem returns the OSV ecosystem for Conda packages. -func (Extractor) Ecosystem(i *extractor.Inventory) string { return "PyPI" } +func (Extractor) Ecosystem(p *extractor.Package) string { return "PyPI" } diff --git a/extractor/filesystem/language/python/condameta/condameta_test.go b/extractor/filesystem/language/python/condameta/condameta_test.go index a0554efe..a1716232 100644 --- a/extractor/filesystem/language/python/condameta/condameta_test.go +++ b/extractor/filesystem/language/python/condameta/condameta_test.go @@ -174,7 +174,7 @@ func TestExtract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/valid", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "jupyterlab", Version: "3.1.12", @@ -230,7 +230,7 @@ func TestExtract(t *testing.T) { return } - if diff := cmp.Diff(tt.WantInventory, got, cmpopts.SortSlices(extracttest.InventoryCmpLess)); diff != "" { + if diff := cmp.Diff(tt.WantPackages, got, cmpopts.SortSlices(extracttest.PackageCmpLess)); diff != "" { t.Errorf("%s.Extract(%q) diff (-want +got):\n%s", e.Name(), tt.InputConfig.Path, diff) } }) @@ -239,7 +239,7 @@ func TestExtract(t *testing.T) { func TestToPURL(t *testing.T) { e := condameta.Extractor{} - i := &extractor.Inventory{ + p := &extractor.Package{ Name: "Name", Version: "1.2.3", Locations: []string{"location"}, @@ -249,8 +249,8 @@ func TestToPURL(t *testing.T) { Name: "name", Version: "1.2.3", } - got := e.ToPURL(i) + got := e.ToPURL(p) if diff := cmp.Diff(want, got); diff != "" { - t.Errorf("ToPURL(%v) (-want +got):\n%s", i, diff) + t.Errorf("ToPURL(%v) (-want +got):\n%s", p, diff) } } diff --git a/extractor/filesystem/language/python/internal/pypipurl/pythonpurl.go b/extractor/filesystem/language/python/internal/pypipurl/pythonpurl.go index e1a51b76..6e628bb1 100644 --- a/extractor/filesystem/language/python/internal/pypipurl/pythonpurl.go +++ b/extractor/filesystem/language/python/internal/pypipurl/pythonpurl.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -// Package pypipurl converts an inventory to a PyPI type PackageURL. +// Package pypipurl converts a package to a PyPI type PackageURL. // TODO(#173, b/365452344): Replace with purl.New() which will contain mapping of all ecosystems package pypipurl @@ -35,11 +35,11 @@ var specialCharRunFinder = regexp.MustCompile("[-_.]+") // // This function does *not* handle package names with invalid characters, and will // return them as is. -func MakePackageURL(i *extractor.Inventory) *purl.PackageURL { - normalizedName := specialCharRunFinder.ReplaceAllLiteralString(strings.ToLower(i.Name), "-") +func MakePackageURL(p *extractor.Package) *purl.PackageURL { + normalizedName := specialCharRunFinder.ReplaceAllLiteralString(strings.ToLower(p.Name), "-") return &purl.PackageURL{ Type: purl.TypePyPi, Name: normalizedName, - Version: i.Version, + Version: p.Version, } } diff --git a/extractor/filesystem/language/python/internal/pypipurl/pythonpurl_test.go b/extractor/filesystem/language/python/internal/pypipurl/pythonpurl_test.go index 44c7912a..5a8d389e 100644 --- a/extractor/filesystem/language/python/internal/pypipurl/pythonpurl_test.go +++ b/extractor/filesystem/language/python/internal/pypipurl/pythonpurl_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -// Package pypipurl converts an inventory to a PyPI type PackageURL. +// Package pypipurl converts a package to a PyPI type PackageURL. package pypipurl_test import ( @@ -27,11 +27,11 @@ import ( func TestMakePackageURL(t *testing.T) { tests := []struct { name string - arg extractor.Inventory + arg extractor.Package want *purl.PackageURL }{ { - arg: extractor.Inventory{ + arg: extractor.Package{ Name: "test", Version: "1.0.0", }, @@ -42,7 +42,7 @@ func TestMakePackageURL(t *testing.T) { }, }, { - arg: extractor.Inventory{ + arg: extractor.Package{ Name: "test-with-dashes", Version: "1.0.0", }, @@ -53,7 +53,7 @@ func TestMakePackageURL(t *testing.T) { }, }, { - arg: extractor.Inventory{ + arg: extractor.Package{ Name: "test_with_underscore", Version: "1.0.0", }, @@ -64,7 +64,7 @@ func TestMakePackageURL(t *testing.T) { }, }, { - arg: extractor.Inventory{ + arg: extractor.Package{ Name: "test___with_long__underscore", Version: "1.0.0", }, @@ -75,7 +75,7 @@ func TestMakePackageURL(t *testing.T) { }, }, { - arg: extractor.Inventory{ + arg: extractor.Package{ Name: "test.with-mixed_symbols", Version: "1.0.0", }, @@ -86,7 +86,7 @@ func TestMakePackageURL(t *testing.T) { }, }, { - arg: extractor.Inventory{ + arg: extractor.Package{ Name: "test.__-with_mixed_.--run", Version: "1.0.0", }, diff --git a/extractor/filesystem/language/python/pdmlock/pdmlock.go b/extractor/filesystem/language/python/pdmlock/pdmlock.go index 1d828e61..8771e538 100644 --- a/extractor/filesystem/language/python/pdmlock/pdmlock.go +++ b/extractor/filesystem/language/python/pdmlock/pdmlock.go @@ -69,35 +69,35 @@ func (e Extractor) FileRequired(api filesystem.FileAPI) bool { } // Extract extracts packages from pdm.lock files passed through the scan input. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { var parsedLockFile *pdmLockFile _, err := toml.NewDecoder(input.Reader).Decode(&parsedLockFile) if err != nil { return nil, fmt.Errorf("could not extract from %s: %w", input.Path, err) } - packages := make([]*extractor.Inventory, 0, len(parsedLockFile.Packages)) + packages := make([]*extractor.Package, 0, len(parsedLockFile.Packages)) - for _, pkg := range parsedLockFile.Packages { - inventory := &extractor.Inventory{ - Name: pkg.Name, - Version: pkg.Version, + for _, parsedPKG := range parsedLockFile.Packages { + pkg := &extractor.Package{ + Name: parsedPKG.Name, + Version: parsedPKG.Version, Locations: []string{input.Path}, } - depGroups := parseGroupsToDepGroups(pkg.Groups) + depGroups := parseGroupsToDepGroups(parsedPKG.Groups) - inventory.Metadata = osv.DepGroupMetadata{ + pkg.Metadata = osv.DepGroupMetadata{ DepGroupVals: depGroups, } - if pkg.Revision != "" { - inventory.SourceCode = &extractor.SourceCodeIdentifier{ - Commit: pkg.Revision, + if parsedPKG.Revision != "" { + pkg.SourceCode = &extractor.SourceCodeIdentifier{ + Commit: parsedPKG.Revision, } } - packages = append(packages, inventory) + packages = append(packages, pkg) } return packages, nil @@ -127,13 +127,13 @@ func parseGroupsToDepGroups(groups []string) []string { return depGroups } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { - return pypipurl.MakePackageURL(i) +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { + return pypipurl.MakePackageURL(p) } // Ecosystem returns the OSV ecosystem ('PyPI') of the software extracted by this extractor. -func (e Extractor) Ecosystem(i *extractor.Inventory) string { +func (e Extractor) Ecosystem(p *extractor.Package) string { return "PyPI" } diff --git a/extractor/filesystem/language/python/pdmlock/pdmlock_test.go b/extractor/filesystem/language/python/pdmlock/pdmlock_test.go index 76c6d334..f58a0e04 100644 --- a/extractor/filesystem/language/python/pdmlock/pdmlock_test.go +++ b/extractor/filesystem/language/python/pdmlock/pdmlock_test.go @@ -88,22 +88,22 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/not-toml.txt", }, - WantErr: extracttest.ContainsErrStr{Str: "could not extract from"}, - WantInventory: nil, + WantErr: extracttest.ContainsErrStr{Str: "could not extract from"}, + WantPackages: nil, }, { Name: "no packages", InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/empty.toml", }, - WantInventory: []*extractor.Inventory{}, + WantPackages: []*extractor.Package{}, }, { Name: "single package", InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/single-package.toml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "toml", Version: "0.10.2", @@ -119,7 +119,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/two-packages.toml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "toml", Version: "0.10.2", @@ -143,7 +143,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/dev-dependency.toml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "toml", Version: "0.10.2", @@ -175,7 +175,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/optional-dependency.toml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "toml", Version: "0.10.2", @@ -207,7 +207,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/git-dependency.toml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "toml", Version: "0.10.2", @@ -237,7 +237,7 @@ func TestExtractor_Extract(t *testing.T) { return } - if diff := cmp.Diff(tt.WantInventory, got, cmpopts.SortSlices(extracttest.InventoryCmpLess)); diff != "" { + if diff := cmp.Diff(tt.WantPackages, got, cmpopts.SortSlices(extracttest.PackageCmpLess)); diff != "" { t.Errorf("%s.Extract(%q) diff (-want +got):\n%s", extr.Name(), tt.InputConfig.Path, diff) } }) diff --git a/extractor/filesystem/language/python/pipfilelock/pipfilelock.go b/extractor/filesystem/language/python/pipfilelock/pipfilelock.go index 9ece8147..37b75a68 100644 --- a/extractor/filesystem/language/python/pipfilelock/pipfilelock.go +++ b/extractor/filesystem/language/python/pipfilelock/pipfilelock.go @@ -69,7 +69,7 @@ func (e Extractor) FileRequired(api filesystem.FileAPI) bool { } // Extract extracts packages from Pipfile.lock files passed through the scan input. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { var parsedLockfile *pipenvLockFile err := json.NewDecoder(input.Reader).Decode(&parsedLockfile) @@ -78,7 +78,7 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] return nil, fmt.Errorf("could not extract from %s: %w", input.Path, err) } - details := make(map[string]*extractor.Inventory) + details := make(map[string]*extractor.Package) addPkgDetails(details, parsedLockfile.Packages, "") addPkgDetails(details, parsedLockfile.PackagesDev, "dev") @@ -90,7 +90,7 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] return maps.Values(details), nil } -func addPkgDetails(details map[string]*extractor.Inventory, packages map[string]pipenvPackage, group string) { +func addPkgDetails(details map[string]*extractor.Package, packages map[string]pipenvPackage, group string) { for name, pipenvPackage := range packages { if pipenvPackage.Version == "" { continue @@ -113,7 +113,7 @@ func addPkgDetails(details map[string]*extractor.Inventory, packages map[string] groupSlice = []string{group} } - inv := &extractor.Inventory{ + pkg := &extractor.Package{ Name: name, Version: version, Metadata: osv.DepGroupMetadata{ @@ -121,18 +121,18 @@ func addPkgDetails(details map[string]*extractor.Inventory, packages map[string] }, } - details[name+"@"+version] = inv + details[name+"@"+version] = pkg } } } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { - return pypipurl.MakePackageURL(i) +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { + return pypipurl.MakePackageURL(p) } // Ecosystem returns the OSV ecosystem ('PyPI') of the software extracted by this extractor. -func (e Extractor) Ecosystem(i *extractor.Inventory) string { +func (e Extractor) Ecosystem(p *extractor.Package) string { return "PyPI" } diff --git a/extractor/filesystem/language/python/pipfilelock/pipfilelock_test.go b/extractor/filesystem/language/python/pipfilelock/pipfilelock_test.go index a63430f1..d4eba379 100644 --- a/extractor/filesystem/language/python/pipfilelock/pipfilelock_test.go +++ b/extractor/filesystem/language/python/pipfilelock/pipfilelock_test.go @@ -82,22 +82,22 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/not-json.txt", }, - WantErr: extracttest.ContainsErrStr{Str: "could not extract from"}, - WantInventory: nil, + WantErr: extracttest.ContainsErrStr{Str: "could not extract from"}, + WantPackages: nil, }, { Name: "no packages", InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/empty.json", }, - WantInventory: []*extractor.Inventory{}, + WantPackages: []*extractor.Package{}, }, { Name: "one package", InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/one-package.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "markupsafe", Version: "2.1.1", @@ -113,7 +113,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/one-package-dev.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "markupsafe", Version: "2.1.1", @@ -129,7 +129,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/two-packages.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "itsdangerous", Version: "2.1.2", @@ -153,7 +153,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/two-packages-alt.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "itsdangerous", Version: "2.1.2", @@ -177,7 +177,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/multiple-packages.json", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "itsdangerous", Version: "2.1.2", @@ -217,7 +217,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/no-version.json", }, - WantInventory: []*extractor.Inventory{}, + WantPackages: []*extractor.Package{}, }, } @@ -235,7 +235,7 @@ func TestExtractor_Extract(t *testing.T) { return } - if diff := cmp.Diff(tt.WantInventory, got, cmpopts.SortSlices(extracttest.InventoryCmpLess)); diff != "" { + if diff := cmp.Diff(tt.WantPackages, got, cmpopts.SortSlices(extracttest.PackageCmpLess)); diff != "" { t.Errorf("%s.Extract(%q) diff (-want +got):\n%s", extr.Name(), tt.InputConfig.Path, diff) } }) diff --git a/extractor/filesystem/language/python/poetrylock/poetrylock.go b/extractor/filesystem/language/python/poetrylock/poetrylock.go index ce19cbed..18eaaaa4 100644 --- a/extractor/filesystem/language/python/poetrylock/poetrylock.go +++ b/extractor/filesystem/language/python/poetrylock/poetrylock.go @@ -97,7 +97,7 @@ func resolveGroups(pkg poetryLockPackage) []string { } // Extract extracts packages from poetry.lock files passed through the scan input. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { var parsedLockfile *poetryLockFile _, err := toml.NewDecoder(input.Reader).Decode(&parsedLockfile) @@ -106,10 +106,10 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] return nil, fmt.Errorf("could not extract from %s: %w", input.Path, err) } - packages := make([]*extractor.Inventory, 0, len(parsedLockfile.Packages)) + packages := make([]*extractor.Package, 0, len(parsedLockfile.Packages)) for _, lockPackage := range parsedLockfile.Packages { - pkgDetails := &extractor.Inventory{ + pkgDetails := &extractor.Package{ Name: lockPackage.Name, Version: lockPackage.Version, Locations: []string{input.Path}, @@ -128,13 +128,13 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] return packages, nil } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { - return pypipurl.MakePackageURL(i) +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { + return pypipurl.MakePackageURL(p) } // Ecosystem returns the OSV ecosystem ('PyPI') of the software extracted by this extractor. -func (e Extractor) Ecosystem(i *extractor.Inventory) string { +func (e Extractor) Ecosystem(p *extractor.Package) string { return "PyPI" } diff --git a/extractor/filesystem/language/python/poetrylock/poetrylock_test.go b/extractor/filesystem/language/python/poetrylock/poetrylock_test.go index 76879d75..ff81a301 100644 --- a/extractor/filesystem/language/python/poetrylock/poetrylock_test.go +++ b/extractor/filesystem/language/python/poetrylock/poetrylock_test.go @@ -82,22 +82,22 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/not-toml.txt", }, - WantErr: extracttest.ContainsErrStr{Str: "could not extract from"}, - WantInventory: nil, + WantErr: extracttest.ContainsErrStr{Str: "could not extract from"}, + WantPackages: nil, }, { Name: "no packages", InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/empty.lock", }, - WantInventory: []*extractor.Inventory{}, + WantPackages: []*extractor.Package{}, }, { Name: "one package", InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/one-package.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "numpy", Version: "1.23.3", @@ -113,7 +113,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/two-packages.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "proto-plus", Version: "1.22.0", @@ -137,7 +137,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/one-package-with-metadata.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "emoji", Version: "2.0.0", @@ -153,7 +153,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/source-git.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "ike", Version: "0.2.0", @@ -172,7 +172,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/source-legacy.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "appdirs", Version: "1.4.4", @@ -188,7 +188,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/optional-package.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "numpy", Version: "1.23.3", @@ -204,7 +204,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/multiple-packages.v2.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "async-timeout", Version: "5.0.1", @@ -311,7 +311,7 @@ func TestExtractor_Extract(t *testing.T) { return } - if diff := cmp.Diff(tt.WantInventory, got, cmpopts.SortSlices(extracttest.InventoryCmpLess)); diff != "" { + if diff := cmp.Diff(tt.WantPackages, got, cmpopts.SortSlices(extracttest.PackageCmpLess)); diff != "" { t.Errorf("%s.Extract(%q) diff (-want +got):\n%s", extr.Name(), tt.InputConfig.Path, diff) } }) diff --git a/extractor/filesystem/language/python/requirements/requirements.go b/extractor/filesystem/language/python/requirements/requirements.go index 37b0914d..16833723 100644 --- a/extractor/filesystem/language/python/requirements/requirements.go +++ b/extractor/filesystem/language/python/requirements/requirements.go @@ -138,10 +138,10 @@ func (e Extractor) reportFileRequired(path string, fileSizeBytes int64, result s type pathQueue []string // Extract extracts packages from requirements files passed through the scan input. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { // Additional paths to recursive files found during extraction. var extraPaths pathQueue - var inv []*extractor.Inventory + var pkgs []*extractor.Package newRepos, newPaths, err := extractFromPath(input.Reader, input.Path, input.FS) if err != nil { return nil, err @@ -150,21 +150,21 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] e.exportStats(input, err) } extraPaths = append(extraPaths, newPaths...) - inv = append(inv, newRepos...) + pkgs = append(pkgs, newRepos...) // Process all the recursive files that we found. - extraInv := extractFromExtraPaths(input.Path, extraPaths, input.FS) - inv = append(inv, extraInv...) + extraPKG := extractFromExtraPaths(input.Path, extraPaths, input.FS) + pkgs = append(pkgs, extraPKG...) - return inv, nil + return pkgs, nil } -func extractFromExtraPaths(initPath string, extraPaths pathQueue, fs scalibrfs.FS) []*extractor.Inventory { - // File paths with inventories already found in this extraction. +func extractFromExtraPaths(initPath string, extraPaths pathQueue, fs scalibrfs.FS) []*extractor.Package { + // File paths with packages already found in this extraction. // We store these to remove duplicates in diamond dependency cases and prevent // infinite loops in misconfigured lockfiles with cyclical deps. var found = map[string]bool{initPath: true} - var inv []*extractor.Inventory + var pkgs []*extractor.Package for len(extraPaths) > 0 { path := extraPaths[0] @@ -172,24 +172,24 @@ func extractFromExtraPaths(initPath string, extraPaths pathQueue, fs scalibrfs.F if _, exists := found[path]; exists { continue } - newInv, newPaths, err := openAndExtractFromFile(path, fs) + newPKG, newPaths, err := openAndExtractFromFile(path, fs) if err != nil { log.Warnf("openAndExtractFromFile(%s): %w", path, err) continue } found[path] = true extraPaths = append(extraPaths, newPaths...) - for _, i := range newInv { + for _, p := range newPKG { // Note the path through which we refer to this requirements.txt file. - i.Locations[0] = initPath + ":" + filepath.ToSlash(i.Locations[0]) + p.Locations[0] = initPath + ":" + filepath.ToSlash(p.Locations[0]) } - inv = append(inv, newInv...) + pkgs = append(pkgs, newPKG...) } - return inv + return pkgs } -func openAndExtractFromFile(path string, fs scalibrfs.FS) ([]*extractor.Inventory, pathQueue, error) { +func openAndExtractFromFile(path string, fs scalibrfs.FS) ([]*extractor.Package, pathQueue, error) { reader, err := fs.Open(filepath.ToSlash(path)) if err != nil { return nil, nil, err @@ -198,8 +198,8 @@ func openAndExtractFromFile(path string, fs scalibrfs.FS) ([]*extractor.Inventor return extractFromPath(reader, path, fs) } -func extractFromPath(reader io.Reader, path string, fs scalibrfs.FS) ([]*extractor.Inventory, pathQueue, error) { - var inv []*extractor.Inventory +func extractFromPath(reader io.Reader, path string, fs scalibrfs.FS) ([]*extractor.Package, pathQueue, error) { + var pkgs []*extractor.Package var extraPaths pathQueue s := bufio.NewScanner(reader) for s.Scan() { @@ -239,7 +239,7 @@ func extractFromPath(reader io.Reader, path string, fs scalibrfs.FS) ([]*extract continue } - inv = append(inv, &extractor.Inventory{ + pkgs = append(pkgs, &extractor.Package{ Name: name, Version: version, Locations: []string{path}, @@ -250,7 +250,7 @@ func extractFromPath(reader io.Reader, path string, fs scalibrfs.FS) ([]*extract }) } - return inv, extraPaths, s.Err() + return pkgs, extraPaths, s.Err() } // readLine reads a line from the scanner, removes comments and joins it with @@ -349,10 +349,10 @@ func splitPerRequirementOptions(s string) (string, []string) { return reTextAfterFirstOptionInclusive.ReplaceAllString(s, ""), hashes } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { - return pypipurl.MakePackageURL(i) +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { + return pypipurl.MakePackageURL(p) } // Ecosystem returns the OSV Ecosystem of the software extracted by this extractor. -func (Extractor) Ecosystem(i *extractor.Inventory) string { return "PyPI" } +func (Extractor) Ecosystem(p *extractor.Package) string { return "PyPI" } diff --git a/extractor/filesystem/language/python/requirements/requirements_test.go b/extractor/filesystem/language/python/requirements/requirements_test.go index 8ee98e58..abda79d1 100644 --- a/extractor/filesystem/language/python/requirements/requirements_test.go +++ b/extractor/filesystem/language/python/requirements/requirements_test.go @@ -134,7 +134,7 @@ func TestExtract(t *testing.T) { tests := []struct { name string path string - wantInventory []*extractor.Inventory + wantPackages []*extractor.Package wantResultMetric stats.FileExtractedResult }{ { @@ -154,7 +154,7 @@ func TestExtract(t *testing.T) { { name: "with version", path: "testdata/with_versions.txt", - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ {Name: "nltk", Version: "3.2.2"}, {Name: "tabulate", Version: "0.7.7"}, { @@ -182,7 +182,7 @@ func TestExtract(t *testing.T) { { name: "comments", path: "testdata/comments.txt", - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ {Name: "PyCrypto", Version: "1.2-alpha"}, {Name: "GMPY2", Version: "1"}, {Name: "SymPy", Version: "1.2"}, @@ -194,7 +194,7 @@ func TestExtract(t *testing.T) { { name: "pip example", path: "testdata/example.txt", - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ // not pytest, because no version // not pytest-cov, because no version // not beautifulsoup4, because no version @@ -223,7 +223,7 @@ func TestExtract(t *testing.T) { { name: "extras", path: "testdata/extras.txt", - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ {Name: "pyjwt", Version: "2.1.0"}, {Name: "celery", Version: "4.4.7"}, }, @@ -232,7 +232,7 @@ func TestExtract(t *testing.T) { { name: "env variable", path: "testdata/env_var.txt", - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ {Name: "asdf", Version: "1.2"}, {Name: "another", Version: "1.0"}, }, @@ -246,7 +246,7 @@ func TestExtract(t *testing.T) { { name: "per requirement options", path: "testdata/per_req_options.txt", - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { // foo1==1.0 --hash=sha256:123 Name: "foo1", @@ -344,18 +344,18 @@ func TestExtract(t *testing.T) { // fill Location and Extractor for _, t := range tests { - for _, i := range t.wantInventory { - if i.Locations == nil { - i.Locations = []string{t.path} + for _, p := range t.wantPackages { + if p.Locations == nil { + p.Locations = []string{t.path} } - if i.Metadata == nil { - i.Metadata = &requirements.Metadata{} + if p.Metadata == nil { + p.Metadata = &requirements.Metadata{} } - if i.Metadata.(*requirements.Metadata).HashCheckingModeValues == nil { - i.Metadata.(*requirements.Metadata).HashCheckingModeValues = []string{} + if p.Metadata.(*requirements.Metadata).HashCheckingModeValues == nil { + p.Metadata.(*requirements.Metadata).HashCheckingModeValues = []string{} } - if i.Metadata.(*requirements.Metadata).VersionComparator == "" { - i.Metadata.(*requirements.Metadata).VersionComparator = "==" + if p.Metadata.(*requirements.Metadata).VersionComparator == "" { + p.Metadata.(*requirements.Metadata).VersionComparator = "==" } } } @@ -389,7 +389,7 @@ func TestExtract(t *testing.T) { t.Fatalf("Extract(%s): %v", tt.path, err) } - want := tt.wantInventory + want := tt.wantPackages if diff := cmp.Diff(want, got); diff != "" { t.Errorf("Extract(%s) (-want +got):\n%s", tt.path, diff) } @@ -409,7 +409,7 @@ func TestExtract(t *testing.T) { func TestToPURL(t *testing.T) { e := requirements.Extractor{} - i := &extractor.Inventory{ + p := &extractor.Package{ Name: "Name", Version: "1.2.3", Locations: []string{"location"}, @@ -420,8 +420,8 @@ func TestToPURL(t *testing.T) { Name: "name", Version: "1.2.3", } - got := e.ToPURL(i) + got := e.ToPURL(p) if diff := cmp.Diff(want, got); diff != "" { - t.Errorf("ToPURL(%v) (-want +got):\n%s", i, diff) + t.Errorf("ToPURL(%v) (-want +got):\n%s", p, diff) } } diff --git a/extractor/filesystem/language/python/setup/setup.go b/extractor/filesystem/language/python/setup/setup.go index 7a953a87..8ed94867 100644 --- a/extractor/filesystem/language/python/setup/setup.go +++ b/extractor/filesystem/language/python/setup/setup.go @@ -125,8 +125,8 @@ func (e Extractor) reportFileRequired(path string, fileSizeBytes int64, result s } // Extract extracts packages from setup.py files passed through the scan input. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { - inventory, err := e.extractFromInput(ctx, input) +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { + pkgs, err := e.extractFromInput(ctx, input) if e.stats != nil { var fileSizeBytes int64 @@ -139,19 +139,19 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] FileSizeBytes: fileSizeBytes, }) } - return inventory, err + return pkgs, err } var packageVersionRe = regexp.MustCompile(`['"]\W?(\w+)\W?(==|>=|<=)\W?([\w.]*)`) -func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { s := bufio.NewScanner(input.Reader) - pkgs := []*extractor.Inventory{} + packages := []*extractor.Package{} for s.Scan() { // Return if canceled or exceeding deadline. if err := ctx.Err(); err != nil { - return pkgs, fmt.Errorf("%s halted at %q because of context error: %v", e.Name(), input.Path, err) + return packages, fmt.Errorf("%s halted at %q because of context error: %v", e.Name(), input.Path, err) } line := s.Text() @@ -176,22 +176,22 @@ func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanI comp := match[2] pkgVersion := strings.TrimSpace(match[3]) - i := &extractor.Inventory{ + p := &extractor.Package{ Name: pkgName, Version: pkgVersion, Locations: []string{input.Path}, Metadata: &Metadata{VersionComparator: comp}, } - pkgs = append(pkgs, i) + packages = append(packages, p) } if s.Err() != nil { - return pkgs, fmt.Errorf("error while scanning setup.py file from %v: %w", input.Path, s.Err()) + return packages, fmt.Errorf("error while scanning setup.py file from %v: %w", input.Path, s.Err()) } } - return pkgs, nil + return packages, nil } func containsTemplate(s string) bool { @@ -199,9 +199,9 @@ func containsTemplate(s string) bool { } // Ecosystem returns the OSV Ecosystem of the software extracted by this extractor. -func (Extractor) Ecosystem(i *extractor.Inventory) string { return "PyPI" } +func (Extractor) Ecosystem(p *extractor.Package) string { return "PyPI" } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { - return pypipurl.MakePackageURL(i) +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { + return pypipurl.MakePackageURL(p) } diff --git a/extractor/filesystem/language/python/setup/setup_test.go b/extractor/filesystem/language/python/setup/setup_test.go index eecc307a..97250cc9 100644 --- a/extractor/filesystem/language/python/setup/setup_test.go +++ b/extractor/filesystem/language/python/setup/setup_test.go @@ -178,7 +178,7 @@ func TestExtract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/valid", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "pysaml2", Version: "6.5.1", @@ -252,7 +252,7 @@ func TestExtract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/valid_2", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "accelerate", Version: "0.26.1", @@ -284,7 +284,7 @@ func TestExtract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/valid_3", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "nanoplotter", Version: "0.13.1", @@ -310,7 +310,7 @@ func TestExtract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/template", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "requests", Version: "2.25.1", @@ -332,18 +332,18 @@ func TestExtract(t *testing.T) { }, }, { - Name: "empty pkg setup.py file", + Name: "empty package setup.py file", InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/empty", }, - WantInventory: []*extractor.Inventory{}, + WantPackages: []*extractor.Package{}, }, { Name: "empty file", InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/empty_2", }, - WantInventory: []*extractor.Inventory{}, + WantPackages: []*extractor.Package{}, }, } @@ -366,7 +366,7 @@ func TestExtract(t *testing.T) { return } - if diff := cmp.Diff(tt.WantInventory, got, cmpopts.SortSlices(extracttest.InventoryCmpLess)); diff != "" { + if diff := cmp.Diff(tt.WantPackages, got, cmpopts.SortSlices(extracttest.PackageCmpLess)); diff != "" { t.Errorf("%s.Extract(%q) diff (-want +got):\n%s", e.Name(), tt.InputConfig.Path, diff) } }) @@ -375,7 +375,7 @@ func TestExtract(t *testing.T) { func TestToPURL(t *testing.T) { e := setup.Extractor{} - i := &extractor.Inventory{ + p := &extractor.Package{ Name: "Name", Version: "1.2.3", Locations: []string{"location"}, @@ -385,9 +385,9 @@ func TestToPURL(t *testing.T) { Name: "name", Version: "1.2.3", } - got := e.ToPURL(i) + got := e.ToPURL(p) if diff := cmp.Diff(want, got); diff != "" { - t.Errorf("ToPURL(%v) (-want +got):\n%s", i, diff) + t.Errorf("ToPURL(%v) (-want +got):\n%s", p, diff) } } diff --git a/extractor/filesystem/language/python/uvlock/uvlock.go b/extractor/filesystem/language/python/uvlock/uvlock.go index 1eb1b72e..0a0210e9 100644 --- a/extractor/filesystem/language/python/uvlock/uvlock.go +++ b/extractor/filesystem/language/python/uvlock/uvlock.go @@ -83,16 +83,16 @@ func (e Extractor) FileRequired(api filesystem.FileAPI) bool { } // Extract extracts packages from uv.lock files passed through the scan input. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { var parsedLockfile *uvLockFile _, err := toml.NewDecoder(input.Reader).Decode(&parsedLockfile) if err != nil { - return []*extractor.Inventory{}, fmt.Errorf("could not extract from %s: %w", input.Path, err) + return []*extractor.Package{}, fmt.Errorf("could not extract from %s: %w", input.Path, err) } - packages := make([]*extractor.Inventory, 0, len(parsedLockfile.Packages)) + packages := make([]*extractor.Package, 0, len(parsedLockfile.Packages)) var groups map[string][]uvOptionalDependency @@ -111,7 +111,7 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] _, commit, _ := strings.Cut(lockPackage.Source.Git, "#") - pkgDetails := &extractor.Inventory{ + pkgDetails := &extractor.Package{ Name: lockPackage.Name, Version: lockPackage.Version, Locations: []string{input.Path}, @@ -144,13 +144,13 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] return packages, nil } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { - return pypipurl.MakePackageURL(i) +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { + return pypipurl.MakePackageURL(p) } // Ecosystem returns the OSV ecosystem ('PyPI') of the software extracted by this extractor. -func (e Extractor) Ecosystem(i *extractor.Inventory) string { +func (e Extractor) Ecosystem(p *extractor.Package) string { return "PyPI" } diff --git a/extractor/filesystem/language/python/uvlock/uvlock_test.go b/extractor/filesystem/language/python/uvlock/uvlock_test.go index bccd328b..2cffdbf0 100644 --- a/extractor/filesystem/language/python/uvlock/uvlock_test.go +++ b/extractor/filesystem/language/python/uvlock/uvlock_test.go @@ -27,10 +27,10 @@ import ( "github.com/google/osv-scalibr/testing/extracttest" ) -func inventory(t *testing.T, name string, version string, location string) *extractor.Inventory { +func pkg(t *testing.T, name string, version string, location string) *extractor.Package { t.Helper() - return &extractor.Inventory{ + return &extractor.Package{ Name: name, Version: version, Locations: []string{location}, @@ -95,37 +95,37 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/not-toml.txt", }, - WantErr: extracttest.ContainsErrStr{Str: "could not extract from"}, - WantInventory: []*extractor.Inventory{}, + WantErr: extracttest.ContainsErrStr{Str: "could not extract from"}, + WantPackages: []*extractor.Package{}, }, { Name: "empty file", InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/empty.lock", }, - WantInventory: []*extractor.Inventory{}, + WantPackages: []*extractor.Package{}, }, { Name: "no dependencies", InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/empty.lock", }, - WantInventory: []*extractor.Inventory{}, + WantPackages: []*extractor.Package{}, }, { Name: "no packages", InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/empty.lock", }, - WantInventory: []*extractor.Inventory{}, + WantPackages: []*extractor.Package{}, }, { Name: "one package", InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/one-package.lock", }, - WantInventory: []*extractor.Inventory{ - inventory(t, "emoji", "2.14.0", "testdata/one-package.lock"), + WantPackages: []*extractor.Package{ + pkg(t, "emoji", "2.14.0", "testdata/one-package.lock"), }, }, { @@ -133,9 +133,9 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/two-packages.lock", }, - WantInventory: []*extractor.Inventory{ - inventory(t, "emoji", "2.14.0", "testdata/two-packages.lock"), - inventory(t, "protobuf", "4.25.5", "testdata/two-packages.lock"), + WantPackages: []*extractor.Package{ + pkg(t, "emoji", "2.14.0", "testdata/two-packages.lock"), + pkg(t, "protobuf", "4.25.5", "testdata/two-packages.lock"), }, }, { @@ -143,7 +143,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/source-git.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "ruff", Version: "0.8.1", @@ -162,8 +162,8 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/grouped-packages.lock", }, - WantInventory: []*extractor.Inventory{ - inventory(t, "emoji", "2.14.0", "testdata/grouped-packages.lock"), + WantPackages: []*extractor.Package{ + pkg(t, "emoji", "2.14.0", "testdata/grouped-packages.lock"), { Name: "click", Version: "8.1.7", @@ -172,7 +172,7 @@ func TestExtractor_Extract(t *testing.T) { DepGroupVals: []string{"cli"}, }, }, - inventory(t, "colorama", "0.4.6", "testdata/grouped-packages.lock"), + pkg(t, "colorama", "0.4.6", "testdata/grouped-packages.lock"), { Name: "black", Version: "24.10.0", @@ -189,15 +189,15 @@ func TestExtractor_Extract(t *testing.T) { DepGroupVals: []string{"test"}, }, }, - inventory(t, "mccabe", "0.7.0", "testdata/grouped-packages.lock"), - inventory(t, "mypy-extensions", "1.0.0", "testdata/grouped-packages.lock"), - inventory(t, "packaging", "24.2", "testdata/grouped-packages.lock"), - inventory(t, "pathspec", "0.12.1", "testdata/grouped-packages.lock"), - inventory(t, "platformdirs", "4.3.6", "testdata/grouped-packages.lock"), - inventory(t, "pycodestyle", "2.12.1", "testdata/grouped-packages.lock"), - inventory(t, "pyflakes", "3.2.0", "testdata/grouped-packages.lock"), - inventory(t, "tomli", "2.2.1", "testdata/grouped-packages.lock"), - inventory(t, "typing-extensions", "4.12.2", "testdata/grouped-packages.lock"), + pkg(t, "mccabe", "0.7.0", "testdata/grouped-packages.lock"), + pkg(t, "mypy-extensions", "1.0.0", "testdata/grouped-packages.lock"), + pkg(t, "packaging", "24.2", "testdata/grouped-packages.lock"), + pkg(t, "pathspec", "0.12.1", "testdata/grouped-packages.lock"), + pkg(t, "platformdirs", "4.3.6", "testdata/grouped-packages.lock"), + pkg(t, "pycodestyle", "2.12.1", "testdata/grouped-packages.lock"), + pkg(t, "pyflakes", "3.2.0", "testdata/grouped-packages.lock"), + pkg(t, "tomli", "2.2.1", "testdata/grouped-packages.lock"), + pkg(t, "typing-extensions", "4.12.2", "testdata/grouped-packages.lock"), }, }, } @@ -216,7 +216,7 @@ func TestExtractor_Extract(t *testing.T) { return } - if diff := cmp.Diff(tt.WantInventory, got, cmpopts.SortSlices(extracttest.InventoryCmpLess)); diff != "" { + if diff := cmp.Diff(tt.WantPackages, got, cmpopts.SortSlices(extracttest.PackageCmpLess)); diff != "" { t.Errorf("%s.Extract(%q) diff (-want +got):\n%s", extr.Name(), tt.InputConfig.Path, diff) } }) diff --git a/extractor/filesystem/language/python/wheelegg/wheelegg.go b/extractor/filesystem/language/python/wheelegg/wheelegg.go index 85d1ad02..e78441a0 100644 --- a/extractor/filesystem/language/python/wheelegg/wheelegg.go +++ b/extractor/filesystem/language/python/wheelegg/wheelegg.go @@ -147,14 +147,14 @@ func (e Extractor) reportFileRequired(path string, fileSizeBytes int64, result s // Extract extracts packages from wheel/egg files passed through the scan input. // For .egg files, input.Info.Size() is required to unzip the file. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) (inventory []*extractor.Inventory, err error) { +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) (pkgs []*extractor.Package, err error) { if strings.HasSuffix(input.Path, ".egg") { - // TODO(b/280417821): In case extractZip returns no inventory, we could parse the filename. - inventory, err = e.extractZip(ctx, input) + // TODO(b/280417821): In case extractZip returns no packages, we could parse the filename. + pkgs, err = e.extractZip(ctx, input) } else { - var i *extractor.Inventory - if i, err = e.extractSingleFile(input.Reader, input.Path); i != nil { - inventory = []*extractor.Inventory{i} + var p *extractor.Package + if p, err = e.extractSingleFile(input.Reader, input.Path); p != nil { + pkgs = []*extractor.Package{p} } } @@ -169,13 +169,13 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) (in FileSizeBytes: fileSizeBytes, }) } - return inventory, err + return pkgs, err } // ErrSizeNotSet will trigger when Info.Size() is not set. var ErrSizeNotSet = errors.New("input.Info is nil, but should have Size set") -func (e Extractor) extractZip(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) extractZip(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { r, err := scalibrfs.NewReaderAt(input.Reader) if err != nil { return nil, fmt.Errorf("newReaderAt(%s): %w", input.Path, err) @@ -189,7 +189,7 @@ func (e Extractor) extractZip(ctx context.Context, input *filesystem.ScanInput) if err != nil { return nil, fmt.Errorf("zip.NewReader(%s): %w", input.Path, err) } - inventory := []*extractor.Inventory{} + pkgs := []*extractor.Package{} for _, f := range zr.File { if ctx.Err() != nil { return nil, ctx.Err() @@ -198,16 +198,16 @@ func (e Extractor) extractZip(ctx context.Context, input *filesystem.ScanInput) if !e.FileRequired(simplefileapi.New(f.Name, f.FileInfo())) { continue } - i, err := e.openAndExtract(f, input) + p, err := e.openAndExtract(f, input) if err != nil { - return inventory, err + return pkgs, err } - inventory = append(inventory, i) + pkgs = append(pkgs, p) } - return inventory, nil + return pkgs, nil } -func (e Extractor) openAndExtract(f *zip.File, input *filesystem.ScanInput) (*extractor.Inventory, error) { +func (e Extractor) openAndExtract(f *zip.File, input *filesystem.ScanInput) (*extractor.Package, error) { r, err := f.Open() if err != nil { return nil, fmt.Errorf("On %q: Open(%s): %w", input.Path, f.Name, err) @@ -215,25 +215,25 @@ func (e Extractor) openAndExtract(f *zip.File, input *filesystem.ScanInput) (*ex defer r.Close() // TODO(b/280438976): Store the path inside the zip file. - i, err := e.extractSingleFile(r, input.Path) + p, err := e.extractSingleFile(r, input.Path) if err != nil { return nil, err } - return i, nil + return p, nil } -func (e Extractor) extractSingleFile(r io.Reader, path string) (*extractor.Inventory, error) { - i, err := parse(r) +func (e Extractor) extractSingleFile(r io.Reader, path string) (*extractor.Package, error) { + p, err := parse(r) if err != nil { return nil, fmt.Errorf("wheelegg.parse(%s): %w", path, err) } - i.Locations = []string{path} - return i, nil + p.Locations = []string{path} + return p, nil } -func parse(r io.Reader) (*extractor.Inventory, error) { +func parse(r io.Reader) (*extractor.Package, error) { rd := textproto.NewReader(bufio.NewReader(r)) h, err := rd.ReadMIMEHeader() name := h.Get("Name") @@ -247,7 +247,7 @@ func parse(r io.Reader) (*extractor.Inventory, error) { return nil, fmt.Errorf("Name or version is empty (name: %q, version: %q)", name, version) } - return &extractor.Inventory{ + return &extractor.Package{ Name: name, Version: version, Metadata: &PythonPackageMetadata{ @@ -257,10 +257,10 @@ func parse(r io.Reader) (*extractor.Inventory, error) { }, nil } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { - return pypipurl.MakePackageURL(i) +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { + return pypipurl.MakePackageURL(p) } // Ecosystem returns the OSV Ecosystem of the software extracted by this extractor. -func (Extractor) Ecosystem(i *extractor.Inventory) string { return "PyPI" } +func (Extractor) Ecosystem(p *extractor.Package) string { return "PyPI" } diff --git a/extractor/filesystem/language/python/wheelegg/wheelegg_test.go b/extractor/filesystem/language/python/wheelegg/wheelegg_test.go index 37905550..712563f4 100644 --- a/extractor/filesystem/language/python/wheelegg/wheelegg_test.go +++ b/extractor/filesystem/language/python/wheelegg/wheelegg_test.go @@ -148,14 +148,14 @@ func TestExtract(t *testing.T) { name string path string cfg wheelegg.Config - wantInventory []*extractor.Inventory + wantPackages []*extractor.Package wantErr error wantResultMetric stats.FileExtractedResult }{ { name: ".dist-info/METADATA", path: "testdata/distinfo_meta", - wantInventory: []*extractor.Inventory{{ + wantPackages: []*extractor.Package{{ Name: "pip", Version: "22.2.2", Locations: []string{"testdata/distinfo_meta"}, @@ -168,7 +168,7 @@ func TestExtract(t *testing.T) { { name: ".egg/EGG-INFO/PKG-INFO", path: "testdata/egginfo_pkginfo", - wantInventory: []*extractor.Inventory{{ + wantPackages: []*extractor.Package{{ Name: "setuptools", Version: "57.4.0", Locations: []string{"testdata/egginfo_pkginfo"}, @@ -181,7 +181,7 @@ func TestExtract(t *testing.T) { { name: ".egg-info", path: "testdata/egginfo", - wantInventory: []*extractor.Inventory{{ + wantPackages: []*extractor.Package{{ Name: "pycups", Version: "2.0.1", Locations: []string{"testdata/egginfo"}, @@ -194,7 +194,7 @@ func TestExtract(t *testing.T) { { name: ".egg-info/PKG-INFO", path: "testdata/pkginfo", - wantInventory: []*extractor.Inventory{{ + wantPackages: []*extractor.Package{{ Name: "httplib2", Version: "0.20.4", Locations: []string{"testdata/pkginfo"}, @@ -208,7 +208,7 @@ func TestExtract(t *testing.T) { { name: "malformed PKG-INFO", path: "testdata/malformed_pkginfo", - wantInventory: []*extractor.Inventory{{ + wantPackages: []*extractor.Package{{ Name: "passlib", Version: "1.7.4", Locations: []string{"testdata/malformed_pkginfo"}, @@ -221,7 +221,7 @@ func TestExtract(t *testing.T) { { name: ".egg", path: "testdata/monotonic-1.6-py3.10.egg", - wantInventory: []*extractor.Inventory{{ + wantPackages: []*extractor.Package{{ Name: "monotonic", Version: "1.6", Locations: []string{"testdata/monotonic-1.6-py3.10.egg"}, @@ -232,9 +232,9 @@ func TestExtract(t *testing.T) { }}, }, { - name: ".egg without PKG-INFO", - path: "testdata/monotonic_no_pkginfo-1.6-py3.10.egg", - wantInventory: []*extractor.Inventory{}, + name: ".egg without PKG-INFO", + path: "testdata/monotonic_no_pkginfo-1.6-py3.10.egg", + wantPackages: []*extractor.Package{}, }, } @@ -268,7 +268,7 @@ func TestExtract(t *testing.T) { t.Fatalf("Extract(%+v) error: got %v, want %v\n", tt.name, err, tt.wantErr) } - want := tt.wantInventory + want := tt.wantPackages if diff := cmp.Diff(want, got); diff != "" { t.Errorf("Extract(%s) (-want +got):\n%s", tt.path, diff) } @@ -307,14 +307,14 @@ func TestExtractWithoutReadAt(t *testing.T) { var e filesystem.Extractor = wheelegg.New(wheelegg.DefaultConfig()) tests := []struct { - name string - path string - wantInventory *extractor.Inventory + name string + path string + wantPackages *extractor.Package }{ { name: ".egg", path: "testdata/monotonic-1.6-py3.10.egg", - wantInventory: &extractor.Inventory{ + wantPackages: &extractor.Package{ Name: "monotonic", Version: "1.6", Locations: []string{"testdata/monotonic-1.6-py3.10.egg"}, @@ -352,7 +352,7 @@ func TestExtractWithoutReadAt(t *testing.T) { t.Fatalf("Extract(%s): %v", tt.path, err) } - want := []*extractor.Inventory{tt.wantInventory} + want := []*extractor.Package{tt.wantPackages} if diff := cmp.Diff(want, got); diff != "" { t.Errorf("Extract(%s) (-want +got):\n%s", tt.path, diff) } @@ -459,7 +459,7 @@ func TestExtractEggWithoutSize(t *testing.T) { func TestToPURL(t *testing.T) { e := wheelegg.Extractor{} - i := &extractor.Inventory{ + p := &extractor.Package{ Name: "Name", Version: "1.2.3", Locations: []string{"location"}, @@ -469,8 +469,8 @@ func TestToPURL(t *testing.T) { Name: "name", Version: "1.2.3", } - got := e.ToPURL(i) + got := e.ToPURL(p) if diff := cmp.Diff(want, got); diff != "" { - t.Errorf("ToPURL(%v) (-want +got):\n%s", i, diff) + t.Errorf("ToPURL(%v) (-want +got):\n%s", p, diff) } } diff --git a/extractor/filesystem/language/r/renvlock/renvlock.go b/extractor/filesystem/language/r/renvlock/renvlock.go index c8d6b387..2d505586 100644 --- a/extractor/filesystem/language/r/renvlock/renvlock.go +++ b/extractor/filesystem/language/r/renvlock/renvlock.go @@ -65,7 +65,7 @@ func (e Extractor) FileRequired(api filesystem.FileAPI) bool { } // Extract extracts packages from renv.lock files passed through the scan input. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { var parsedLockfile *renvLockfile err := json.NewDecoder(input.Reader).Decode(&parsedLockfile) @@ -74,7 +74,7 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] return nil, fmt.Errorf("could not extract from %s: %w", input.Path, err) } - packages := make([]*extractor.Inventory, 0, len(parsedLockfile.Packages)) + packages := make([]*extractor.Package, 0, len(parsedLockfile.Packages)) for _, pkg := range parsedLockfile.Packages { // currently we only support CRAN @@ -82,7 +82,7 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] continue } - packages = append(packages, &extractor.Inventory{ + packages = append(packages, &extractor.Package{ Name: pkg.Package, Version: pkg.Version, Locations: []string{input.Path}, @@ -92,17 +92,17 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] return packages, nil } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { return &purl.PackageURL{ Type: purl.TypeCran, - Name: i.Name, - Version: i.Version, + Name: p.Name, + Version: p.Version, } } // Ecosystem returns the OSV ecosystem ('CRAN') of the software extracted by this extractor. -func (e Extractor) Ecosystem(i *extractor.Inventory) string { +func (e Extractor) Ecosystem(p *extractor.Package) string { return "CRAN" } diff --git a/extractor/filesystem/language/r/renvlock/renvlock_test.go b/extractor/filesystem/language/r/renvlock/renvlock_test.go index 541c244d..e9d1519e 100644 --- a/extractor/filesystem/language/r/renvlock/renvlock_test.go +++ b/extractor/filesystem/language/r/renvlock/renvlock_test.go @@ -32,22 +32,22 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/not-json.txt", }, - WantInventory: nil, - WantErr: extracttest.ContainsErrStr{Str: "could not extract from"}, + WantPackages: nil, + WantErr: extracttest.ContainsErrStr{Str: "could not extract from"}, }, { Name: "no packages", InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/empty.lock", }, - WantInventory: []*extractor.Inventory{}, + WantPackages: []*extractor.Package{}, }, { Name: "one package", InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/one-package.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "morning", Version: "0.1.0", @@ -60,7 +60,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/two-packages.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "markdown", Version: "1.0", @@ -78,7 +78,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/with-mixed-sources.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "markdown", Version: "1.0", @@ -91,7 +91,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/with-bioconductor.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "BH", Version: "1.75.0-0", @@ -104,7 +104,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/without-repository.lock", }, - WantInventory: []*extractor.Inventory{}, + WantPackages: []*extractor.Package{}, }, } @@ -122,7 +122,7 @@ func TestExtractor_Extract(t *testing.T) { return } - if diff := cmp.Diff(tt.WantInventory, got, cmpopts.SortSlices(extracttest.InventoryCmpLess)); diff != "" { + if diff := cmp.Diff(tt.WantPackages, got, cmpopts.SortSlices(extracttest.PackageCmpLess)); diff != "" { t.Errorf("%s.Extract(%q) diff (-want +got):\n%s", extr.Name(), tt.InputConfig.Path, diff) } }) diff --git a/extractor/filesystem/language/ruby/gemfilelock/gemfilelock.go b/extractor/filesystem/language/ruby/gemfilelock/gemfilelock.go index 25de7371..5b73a4d5 100644 --- a/extractor/filesystem/language/ruby/gemfilelock/gemfilelock.go +++ b/extractor/filesystem/language/ruby/gemfilelock/gemfilelock.go @@ -109,13 +109,13 @@ func parseLockfileSections(input *filesystem.ScanInput) ([]*gemlockSection, erro return sections, nil } -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { sections, err := parseLockfileSections(input) if err != nil { return nil, fmt.Errorf("error parsing %s: %w", input.Path, err) } - invs := []*extractor.Inventory{} + pkgs := []*extractor.Package{} for _, section := range sections { if !slices.Contains([]string{"GIT", "GEM", "PATH", "PLUGIN SOURCE"}, section.name) { // Not a source section. @@ -128,33 +128,33 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] continue } name, version := m[1], m[2] - i := &extractor.Inventory{ + p := &extractor.Package{ Name: name, Version: version, Locations: []string{input.Path}, } if section.revision != "" { - i.SourceCode = &extractor.SourceCodeIdentifier{ + p.SourceCode = &extractor.SourceCodeIdentifier{ Commit: section.revision, } } - invs = append(invs, i) + pkgs = append(pkgs, p) } } - return invs, nil + return pkgs, nil } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { return &purl.PackageURL{ Type: purl.TypeGem, - Name: i.Name, - Version: i.Version, + Name: p.Name, + Version: p.Version, } } // Ecosystem returns the OSV Ecosystem of the software extracted by this extractor. -func (e Extractor) Ecosystem(i *extractor.Inventory) string { +func (e Extractor) Ecosystem(p *extractor.Package) string { return "RubyGems" } diff --git a/extractor/filesystem/language/ruby/gemfilelock/gemfilelock_test.go b/extractor/filesystem/language/ruby/gemfilelock/gemfilelock_test.go index c1492c8e..bb7e913e 100644 --- a/extractor/filesystem/language/ruby/gemfilelock/gemfilelock_test.go +++ b/extractor/filesystem/language/ruby/gemfilelock/gemfilelock_test.go @@ -74,35 +74,35 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/no-spec-section.lock", }, - WantInventory: []*extractor.Inventory{}, + WantPackages: []*extractor.Package{}, }, { Name: "no gem section", InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/no-gem-section.lock", }, - WantInventory: []*extractor.Inventory{}, + WantPackages: []*extractor.Package{}, }, { Name: "no gems", InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/no-gems.lock", }, - WantInventory: []*extractor.Inventory{}, + WantPackages: []*extractor.Package{}, }, { Name: "invalid spec", InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/invalid.lock", }, - WantInventory: []*extractor.Inventory{}, + WantPackages: []*extractor.Package{}, }, { Name: "one gem", InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/one-gem.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "ast", Version: "2.4.2", @@ -115,7 +115,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/source-section-at-end.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "ast", Version: "2.4.2", @@ -128,7 +128,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/some-gems.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "coderay", Version: "1.1.3", @@ -151,7 +151,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/multiple-gems.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "bundler-audit", Version: "0.9.0.1", @@ -189,7 +189,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/rails.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "actioncable", Version: "7.0.2.2", @@ -427,7 +427,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/rubocop.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "ast", Version: "2.4.2", @@ -485,7 +485,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/has-local-gem.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "backbone-on-rails", Version: "1.2.0.0", @@ -643,7 +643,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/has-git-gem.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "hanami-controller", Version: "2.0.0.alpha1", @@ -693,7 +693,7 @@ func TestExtractor_Extract(t *testing.T) { return } - if diff := cmp.Diff(tt.WantInventory, got, cmpopts.SortSlices(extracttest.InventoryCmpLess)); diff != "" { + if diff := cmp.Diff(tt.WantPackages, got, cmpopts.SortSlices(extracttest.PackageCmpLess)); diff != "" { t.Errorf("%s.Extract(%q) diff (-want +got):\n%s", extr.Name(), tt.InputConfig.Path, diff) } }) diff --git a/extractor/filesystem/language/ruby/gemspec/gemspec.go b/extractor/filesystem/language/ruby/gemspec/gemspec.go index b4967aee..b5b78812 100644 --- a/extractor/filesystem/language/ruby/gemspec/gemspec.go +++ b/extractor/filesystem/language/ruby/gemspec/gemspec.go @@ -125,18 +125,18 @@ func (e Extractor) reportFileRequired(path string, fileSizeBytes int64, result s } // Extract extracts packages from the .gemspec file. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { - i, err := extract(input.Path, input.Reader) +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { + p, err := extract(input.Path, input.Reader) e.reportFileExtracted(input.Path, input.Info, filesystem.ExtractorErrorToFileExtractedResult(err)) if err != nil { return nil, fmt.Errorf("gemspec.parse(%s): %w", input.Path, err) } - if i == nil { - return []*extractor.Inventory{}, nil + if p == nil { + return []*extractor.Package{}, nil } - i.Locations = []string{input.Path} - return []*extractor.Inventory{i}, nil + p.Locations = []string{input.Path} + return []*extractor.Package{p}, nil } func (e Extractor) reportFileExtracted(path string, fileinfo fs.FileInfo, result stats.FileExtractedResult) { @@ -157,7 +157,7 @@ func (e Extractor) reportFileExtracted(path string, fileinfo fs.FileInfo, result // extract searches for the required name and version lines in the gemspec // file using regex. // Based on: https://guides.rubygems.org/specification-reference/ -func extract(path string, r io.Reader) (*extractor.Inventory, error) { +func extract(path string, r io.Reader) (*extractor.Package, error) { buf := bufio.NewScanner(r) gemName, gemVer := "", "" foundStart := false @@ -205,20 +205,20 @@ func extract(path string, r io.Reader) (*extractor.Inventory, error) { return nil, fmt.Errorf("failed to parse gemspec name (%v) and version (%v)", gemName, gemVer) } - return &extractor.Inventory{ + return &extractor.Package{ Name: gemName, Version: gemVer, }, nil } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { return &purl.PackageURL{ Type: purl.TypeGem, - Name: i.Name, - Version: i.Version, + Name: p.Name, + Version: p.Version, } } // Ecosystem returns the OSV Ecosystem of the software extracted by this extractor. -func (Extractor) Ecosystem(i *extractor.Inventory) string { return "RubyGems" } +func (Extractor) Ecosystem(p *extractor.Package) string { return "RubyGems" } diff --git a/extractor/filesystem/language/ruby/gemspec/gemspec_test.go b/extractor/filesystem/language/ruby/gemspec/gemspec_test.go index 341281b8..88236696 100644 --- a/extractor/filesystem/language/ruby/gemspec/gemspec_test.go +++ b/extractor/filesystem/language/ruby/gemspec/gemspec_test.go @@ -126,14 +126,14 @@ func TestExtract(t *testing.T) { tests := []struct { name string path string - wantInventory []*extractor.Inventory + wantPackages []*extractor.Package wantErr error wantResultMetric stats.FileExtractedResult }{ { name: "yaml gemspec", path: "testdata/yaml-0.2.1.gemspec", - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "yaml", Version: "0.2.1", @@ -145,7 +145,7 @@ func TestExtract(t *testing.T) { { name: "rss gemspec", path: "testdata/rss-0.2.9.gemspec", - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "rss", Version: "0.2.9", @@ -163,13 +163,13 @@ func TestExtract(t *testing.T) { { name: "empty gemspec", path: "testdata/empty.gemspec", - wantInventory: []*extractor.Inventory{}, + wantPackages: []*extractor.Package{}, wantResultMetric: stats.FileExtractedResultSuccess, }, { name: "bad definition gemspec", path: "testdata/badspec.gemspec", - wantInventory: []*extractor.Inventory{}, + wantPackages: []*extractor.Package{}, wantResultMetric: stats.FileExtractedResultSuccess, }, } @@ -200,9 +200,9 @@ func TestExtract(t *testing.T) { t.Fatalf("Extract(%+v) error: got %v, want %v\n", test.name, err, test.wantErr) } - var want []*extractor.Inventory - if test.wantInventory != nil { - want = test.wantInventory + var want []*extractor.Package + if test.wantPackages != nil { + want = test.wantPackages } if diff := cmp.Diff(want, got); diff != "" { @@ -224,7 +224,7 @@ func TestExtract(t *testing.T) { func TestToPURL(t *testing.T) { e := gemspec.Extractor{} - i := &extractor.Inventory{ + p := &extractor.Package{ Name: "name", Version: "1.2.3", Locations: []string{"location"}, @@ -234,8 +234,8 @@ func TestToPURL(t *testing.T) { Name: "name", Version: "1.2.3", } - got := e.ToPURL(i) + got := e.ToPURL(p) if diff := cmp.Diff(want, got); diff != "" { - t.Errorf("ToPURL(%v) (-want +got):\n%s", i, diff) + t.Errorf("ToPURL(%v) (-want +got):\n%s", p, diff) } } diff --git a/extractor/filesystem/language/rust/cargoauditable/cargoauditable.go b/extractor/filesystem/language/rust/cargoauditable/cargoauditable.go index 26742966..b758a206 100644 --- a/extractor/filesystem/language/rust/cargoauditable/cargoauditable.go +++ b/extractor/filesystem/language/rust/cargoauditable/cargoauditable.go @@ -126,7 +126,7 @@ func (e Extractor) FileRequired(api filesystem.FileAPI) bool { } // Extract extracts packages from cargo auditable inside rust binaries. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { reader, ok := input.Reader.(io.ReaderAt) if !ok { return nil, fmt.Errorf("input.Reader is not a ReaderAt") @@ -137,25 +137,25 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] // Most errors are just that the file is not a cargo auditable rust binary. if err != nil { if errors.Is(err, rustaudit.ErrUnknownFileFormat) || errors.Is(err, rustaudit.ErrNoRustDepInfo) { - return []*extractor.Inventory{}, nil + return []*extractor.Package{}, nil } log.Debugf("error getting dependency information from binary (%s) for extraction: %v", input.Path, err) return nil, fmt.Errorf("rustaudit.GetDependencyInfo(%q): %w", input.Path, err) } - inventory := []*extractor.Inventory{} + pkgs := []*extractor.Package{} for _, dep := range dependencyInfo.Packages { // Cargo auditable also tracks build-only dependencies which we may not want to report. // Note: the main package is reported as a runtime dependency. if dep.Kind == rustaudit.Runtime || e.extractBuildDependencies { - inventory = append(inventory, &extractor.Inventory{ + pkgs = append(pkgs, &extractor.Package{ Name: dep.Name, Version: dep.Version, Locations: []string{input.Path}, }) } } - return inventory, nil + return pkgs, nil } func (e Extractor) reportFileExtracted(input *filesystem.ScanInput, result stats.FileExtractedResult) { @@ -169,17 +169,17 @@ func (e Extractor) reportFileExtracted(input *filesystem.ScanInput, result stats }) } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { return &purl.PackageURL{ Type: purl.TypeCargo, - Name: i.Name, - Version: i.Version, + Name: p.Name, + Version: p.Version, } } // Ecosystem returns the OSV ecosystem ('crates.io') of the software extracted by this extractor. -func (e Extractor) Ecosystem(_ *extractor.Inventory) string { +func (e Extractor) Ecosystem(_ *extractor.Package) string { return "crates.io" } diff --git a/extractor/filesystem/language/rust/cargoauditable/cargoauditable_test.go b/extractor/filesystem/language/rust/cargoauditable/cargoauditable_test.go index c1a22889..b075fe82 100644 --- a/extractor/filesystem/language/rust/cargoauditable/cargoauditable_test.go +++ b/extractor/filesystem/language/rust/cargoauditable/cargoauditable_test.go @@ -114,7 +114,7 @@ func TestFileRequired(t *testing.T) { func TestToPURL(t *testing.T) { cargoAuditableExtractor := cargoauditable.Extractor{} - inventory := &extractor.Inventory{ + pkg := &extractor.Package{ Name: "name", Version: "1.2.3", Locations: []string{"location"}, @@ -124,9 +124,9 @@ func TestToPURL(t *testing.T) { Name: "name", Version: "1.2.3", } - got := cargoAuditableExtractor.ToPURL(inventory) + got := cargoAuditableExtractor.ToPURL(pkg) if diff := cmp.Diff(want, got); diff != "" { - t.Errorf("ToPURL(%v) (-want +got):\n%s", inventory, diff) + t.Errorf("ToPURL(%v) (-want +got):\n%s", pkg, diff) } } @@ -134,14 +134,14 @@ func TestExtract(t *testing.T) { tests := []struct { name string path string - wantInventory []*extractor.Inventory + wantPackages []*extractor.Package wantErr error wantResultMetric stats.FileExtractedResult }{ { name: "uses_serde_json", path: "testdata/uses_serde_json/uses_serde_json", - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "itoa", Version: "1.0.14", @@ -202,7 +202,7 @@ func TestExtract(t *testing.T) { { name: "no_deps", path: "testdata/no_deps/no_deps", - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "no_deps", Version: "0.1.0", @@ -213,7 +213,7 @@ func TestExtract(t *testing.T) { { name: "not_binary", path: "testdata/not_binary/not_binary", - wantInventory: []*extractor.Inventory{}, + wantPackages: []*extractor.Package{}, wantResultMetric: stats.FileExtractedResultErrorUnknown, }, } @@ -240,8 +240,8 @@ func TestExtract(t *testing.T) { if err != tt.wantErr { t.Fatalf("Extract(%s) got error: %v, want error: %v", tt.path, err, tt.wantErr) } - sort := func(a, b *extractor.Inventory) bool { return a.Name < b.Name } - if diff := cmp.Diff(tt.wantInventory, got, cmpopts.SortSlices(sort)); diff != "" { + sort := func(a, b *extractor.Package) bool { return a.Name < b.Name } + if diff := cmp.Diff(tt.wantPackages, got, cmpopts.SortSlices(sort)); diff != "" { t.Fatalf("Extract(%s) (-want +got):\n%s", tt.path, diff) } diff --git a/extractor/filesystem/language/rust/cargolock/cargolock.go b/extractor/filesystem/language/rust/cargolock/cargolock.go index 52cd3231..9c95d439 100644 --- a/extractor/filesystem/language/rust/cargolock/cargolock.go +++ b/extractor/filesystem/language/rust/cargolock/cargolock.go @@ -66,7 +66,7 @@ func (e Extractor) Requirements() *plugin.Capabilities { } // Extract extracts packages from Cargo.lock files passed through the scan input. -func (e Extractor) Extract(_ context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) Extract(_ context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { var parsedLockfile *cargoLockFile _, err := toml.NewDecoder(input.Reader).Decode(&parsedLockfile) @@ -75,10 +75,10 @@ func (e Extractor) Extract(_ context.Context, input *filesystem.ScanInput) ([]*e return nil, fmt.Errorf("could not extract from %s: %w", input.Path, err) } - packages := make([]*extractor.Inventory, 0, len(parsedLockfile.Packages)) + packages := make([]*extractor.Package, 0, len(parsedLockfile.Packages)) for _, lockPackage := range parsedLockfile.Packages { - packages = append(packages, &extractor.Inventory{ + packages = append(packages, &extractor.Package{ Name: lockPackage.Name, Version: lockPackage.Version, Locations: []string{input.Path}, @@ -88,17 +88,17 @@ func (e Extractor) Extract(_ context.Context, input *filesystem.ScanInput) ([]*e return packages, nil } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { return &purl.PackageURL{ Type: purl.TypeCargo, - Name: i.Name, - Version: i.Version, + Name: p.Name, + Version: p.Version, } } // Ecosystem returns the OSV ecosystem ('crates.io') of the software extracted by this extractor. -func (e Extractor) Ecosystem(_ *extractor.Inventory) string { +func (e Extractor) Ecosystem(_ *extractor.Package) string { return "crates.io" } diff --git a/extractor/filesystem/language/rust/cargolock/cargolock_test.go b/extractor/filesystem/language/rust/cargolock/cargolock_test.go index e9d69395..1ed5ff00 100644 --- a/extractor/filesystem/language/rust/cargolock/cargolock_test.go +++ b/extractor/filesystem/language/rust/cargolock/cargolock_test.go @@ -83,22 +83,22 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/not-toml.txt", }, - WantInventory: nil, - WantErr: extracttest.ContainsErrStr{Str: "could not extract from"}, + WantPackages: nil, + WantErr: extracttest.ContainsErrStr{Str: "could not extract from"}, }, { Name: "no packages", InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/empty.lock", }, - WantInventory: []*extractor.Inventory{}, + WantPackages: []*extractor.Package{}, }, { Name: "one package", InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/one-package.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "addr2line", Version: "0.15.2", @@ -111,7 +111,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/two-packages.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "addr2line", Version: "0.15.2", @@ -129,7 +129,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/two-packages-with-local.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "addr2line", Version: "0.15.2", @@ -147,7 +147,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/package-with-build-string.lock", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "wasi", Version: "0.10.2+wasi-snapshot-preview1", @@ -170,7 +170,7 @@ func TestExtractor_Extract(t *testing.T) { return } - if diff := cmp.Diff(tt.WantInventory, got, cmpopts.SortSlices(extracttest.InventoryCmpLess)); diff != "" { + if diff := cmp.Diff(tt.WantPackages, got, cmpopts.SortSlices(extracttest.PackageCmpLess)); diff != "" { t.Errorf("%s.Extract(%q) diff (-want +got):\n%s", extr.Name(), tt.InputConfig.Path, diff) } }) diff --git a/extractor/filesystem/language/rust/cargotoml/cargotoml.go b/extractor/filesystem/language/rust/cargotoml/cargotoml.go index eedf3a70..6a7a6f86 100644 --- a/extractor/filesystem/language/rust/cargotoml/cargotoml.go +++ b/extractor/filesystem/language/rust/cargotoml/cargotoml.go @@ -138,7 +138,7 @@ func (e Extractor) Requirements() *plugin.Capabilities { } // Extract extracts packages from Cargo.toml files passed through the scan input. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { var parsedTomlFile cargoTomlFile _, err := toml.NewDecoder(input.Reader).Decode(&parsedTomlFile) @@ -146,9 +146,9 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] return nil, fmt.Errorf("could not extract from %s: %w", input.Path, err) } - packages := make([]*extractor.Inventory, 0, len(parsedTomlFile.Dependencies)+1) + packages := make([]*extractor.Package, 0, len(parsedTomlFile.Dependencies)+1) - packages = append(packages, &extractor.Inventory{ + packages = append(packages, &extractor.Package{ Name: parsedTomlFile.Package.Name, Version: parsedTomlFile.Package.Version, Locations: []string{input.Path}, @@ -172,7 +172,7 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] continue } - packages = append(packages, &extractor.Inventory{ + packages = append(packages, &extractor.Package{ Name: name, Version: dependency.Version, Locations: []string{input.Path}, @@ -183,17 +183,17 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] return packages, nil } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { return &purl.PackageURL{ Type: purl.TypeCargo, - Name: i.Name, - Version: i.Version, + Name: p.Name, + Version: p.Version, } } // Ecosystem returns the OSV ecosystem ('crates.io') of the software extracted by this extractor. -func (e Extractor) Ecosystem(_ *extractor.Inventory) string { +func (e Extractor) Ecosystem(_ *extractor.Package) string { return "crates.io" } diff --git a/extractor/filesystem/language/rust/cargotoml/cargotoml_test.go b/extractor/filesystem/language/rust/cargotoml/cargotoml_test.go index 7235995f..4ef665d3 100644 --- a/extractor/filesystem/language/rust/cargotoml/cargotoml_test.go +++ b/extractor/filesystem/language/rust/cargotoml/cargotoml_test.go @@ -82,23 +82,23 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/not-toml.txt", }, - WantInventory: nil, - WantErr: extracttest.ContainsErrStr{Str: "could not extract from"}, + WantPackages: nil, + WantErr: extracttest.ContainsErrStr{Str: "could not extract from"}, }, { Name: "Invalid dependency toml", InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/invalid-dependency.toml", }, - WantInventory: nil, - WantErr: extracttest.ContainsErrStr{Str: "could not extract from"}, + WantPackages: nil, + WantErr: extracttest.ContainsErrStr{Str: "could not extract from"}, }, { Name: "no dependencies", InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/no-dependency.toml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "hello_world", Version: "0.1.0", @@ -111,7 +111,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/only-version-dependency.toml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "hello_world", Version: "0.1.0", @@ -130,7 +130,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/git-dependency-tagged.toml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "hello_world", Version: "0.1.0", @@ -143,7 +143,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/git-dependency-with-commit.toml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "hello_world", Version: "0.1.0", @@ -164,7 +164,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/git-dependency-with-pr.toml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "hello_world", Version: "0.1.0", @@ -177,7 +177,7 @@ func TestExtractor_Extract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/two-dependencies.toml", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "hello_world", Version: "0.1.0", @@ -206,7 +206,7 @@ func TestExtractor_Extract(t *testing.T) { return } - if diff := cmp.Diff(tt.WantInventory, got, cmpopts.SortSlices(extracttest.InventoryCmpLess)); diff != "" { + if diff := cmp.Diff(tt.WantPackages, got, cmpopts.SortSlices(extracttest.PackageCmpLess)); diff != "" { t.Errorf("%s.Extract(%q) diff (-want +got):\n%s", extr.Name(), tt.InputConfig.Path, diff) } }) diff --git a/extractor/filesystem/language/swift/packageresolved/packageresolved.go b/extractor/filesystem/language/swift/packageresolved/packageresolved.go index 73e29be1..fe7324bc 100644 --- a/extractor/filesystem/language/swift/packageresolved/packageresolved.go +++ b/extractor/filesystem/language/swift/packageresolved/packageresolved.go @@ -117,8 +117,8 @@ func (e Extractor) reportFileRequired(path string, fileSizeBytes int64, result s } // Extract parses and extracts dependency data from a Package.resolved file. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { - inventory, err := e.extractFromInput(ctx, input) +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { + pkgs, err := e.extractFromInput(ctx, input) if e.stats != nil { var fileSizeBytes int64 if input.Info != nil { @@ -130,31 +130,30 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] FileSizeBytes: fileSizeBytes, }) } - return inventory, err + return pkgs, err } -func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { - pkgs, err := parse(input.Reader) +func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { + packages, err := parse(input.Reader) if err != nil { return nil, err } - var inventories []*extractor.Inventory - for _, pkg := range pkgs { - i := &extractor.Inventory{ + var result []*extractor.Package + for _, pkg := range packages { + result = append(result, &extractor.Package{ Name: pkg.Name, Version: pkg.Version, Locations: []string{ input.Path, }, - } - inventories = append(inventories, i) + }) } - return inventories, nil + return result, nil } -// Package represents a parsed package entry from the Package.resolved file. +// pkg represents a parsed package entry from the Package.resolved file. type pkg struct { Name string Version string @@ -186,14 +185,14 @@ func parse(r io.Reader) ([]pkg, error) { return packages, nil } -// ToPURL converts an inventory item into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { +// ToPURL converts a package item into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { return &purl.PackageURL{ Type: purl.TypeCocoapods, - Name: i.Name, - Version: i.Version, + Name: p.Name, + Version: p.Version, } } // Ecosystem returns the OSV Ecosystem for Swift. -func (Extractor) Ecosystem(i *extractor.Inventory) string { return "Cocoapods" } +func (Extractor) Ecosystem(p *extractor.Package) string { return "Cocoapods" } diff --git a/extractor/filesystem/language/swift/packageresolved/packageresolved_test.go b/extractor/filesystem/language/swift/packageresolved/packageresolved_test.go index 7e666f21..9876b598 100644 --- a/extractor/filesystem/language/swift/packageresolved/packageresolved_test.go +++ b/extractor/filesystem/language/swift/packageresolved/packageresolved_test.go @@ -165,7 +165,7 @@ func TestExtract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/valid", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "swift-algorithms", Version: "1.0.0", @@ -217,7 +217,7 @@ func TestExtract(t *testing.T) { return } - if diff := cmp.Diff(tt.WantInventory, got, cmpopts.SortSlices(extracttest.InventoryCmpLess)); diff != "" { + if diff := cmp.Diff(tt.WantPackages, got, cmpopts.SortSlices(extracttest.PackageCmpLess)); diff != "" { t.Errorf("%s.Extract(%q) diff (-want +got):\n%s", e.Name(), tt.InputConfig.Path, diff) } }) @@ -226,7 +226,7 @@ func TestExtract(t *testing.T) { func TestToPURL(t *testing.T) { e := packageresolved.Extractor{} - i := &extractor.Inventory{ + p := &extractor.Package{ Name: "Name", Version: "1.2.3", Locations: []string{"location"}, @@ -236,8 +236,8 @@ func TestToPURL(t *testing.T) { Name: "Name", Version: "1.2.3", } - got := e.ToPURL(i) + got := e.ToPURL(p) if diff := cmp.Diff(want, got); diff != "" { - t.Errorf("ToPURL(%v) (-want +got):\n%s", i, diff) + t.Errorf("ToPURL(%v) (-want +got):\n%s", p, diff) } } diff --git a/extractor/filesystem/language/swift/podfilelock/podfilelock.go b/extractor/filesystem/language/swift/podfilelock/podfilelock.go index d049d3a4..377063ca 100644 --- a/extractor/filesystem/language/swift/podfilelock/podfilelock.go +++ b/extractor/filesystem/language/swift/podfilelock/podfilelock.go @@ -112,8 +112,8 @@ func (e Extractor) reportFileRequired(path string, fileSizeBytes int64, result s } // Extract processes and extracts dependency information from a Podfile.lock file. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { - inventory, err := e.extractFromInput(ctx, input) +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { + pkgs, err := e.extractFromInput(ctx, input) if e.stats != nil { var fileSizeBytes int64 if input.Info != nil { @@ -125,35 +125,35 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] FileSizeBytes: fileSizeBytes, }) } - return inventory, err + return pkgs, err } -func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { - pkgs, err := swiftutils.ParsePodfileLock(input.Reader) +func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { + packages, err := swiftutils.ParsePodfileLock(input.Reader) if err != nil { return nil, err } - var inventories []*extractor.Inventory - for _, pkg := range pkgs { - inventories = append(inventories, &extractor.Inventory{ + var result []*extractor.Package + for _, pkg := range packages { + result = append(result, &extractor.Package{ Name: pkg.Name, Version: pkg.Version, Locations: []string{input.Path}, }) } - return inventories, nil + return result, nil } -// ToPURL converts an inventory item into a Package URL (PURL). -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { +// ToPURL converts a package item into a Package URL (PURL). +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { return &purl.PackageURL{ Type: purl.TypeCocoapods, - Name: i.Name, - Version: i.Version, + Name: p.Name, + Version: p.Version, } } // Ecosystem returns the OSV ecosystem name for CocoaPods. -func (Extractor) Ecosystem(_ *extractor.Inventory) string { return "CocoaPods" } +func (Extractor) Ecosystem(_ *extractor.Package) string { return "CocoaPods" } diff --git a/extractor/filesystem/language/swift/podfilelock/podfilelock_test.go b/extractor/filesystem/language/swift/podfilelock/podfilelock_test.go index 9e9e1dfe..43a8df6b 100644 --- a/extractor/filesystem/language/swift/podfilelock/podfilelock_test.go +++ b/extractor/filesystem/language/swift/podfilelock/podfilelock_test.go @@ -165,7 +165,7 @@ func TestExtract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/valid", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "GlossButtonNode", Version: "3.1.2", @@ -183,7 +183,7 @@ func TestExtract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/valid2", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "GlossButtonNode", Version: "3.1.2", @@ -240,7 +240,7 @@ func TestExtract(t *testing.T) { return } - if diff := cmp.Diff(tt.WantInventory, got, cmpopts.SortSlices(extracttest.InventoryCmpLess)); diff != "" { + if diff := cmp.Diff(tt.WantPackages, got, cmpopts.SortSlices(extracttest.PackageCmpLess)); diff != "" { t.Errorf("%s.Extract(%q) diff (-want +got):\n%s", e.Name(), tt.InputConfig.Path, diff) } }) @@ -249,7 +249,7 @@ func TestExtract(t *testing.T) { func TestToPURL(t *testing.T) { e := podfilelock.Extractor{} - i := &extractor.Inventory{ + p := &extractor.Package{ Name: "Name", Version: "1.2.3", Locations: []string{"location"}, @@ -259,8 +259,8 @@ func TestToPURL(t *testing.T) { Name: "Name", Version: "1.2.3", } - got := e.ToPURL(i) + got := e.ToPURL(p) if diff := cmp.Diff(want, got); diff != "" { - t.Errorf("ToPURL(%v) (-want +got):\n%s", i, diff) + t.Errorf("ToPURL(%v) (-want +got):\n%s", p, diff) } } diff --git a/extractor/filesystem/language/wordpress/plugins/plugins.go b/extractor/filesystem/language/wordpress/plugins/plugins.go index f0fbb946..ef299891 100644 --- a/extractor/filesystem/language/wordpress/plugins/plugins.go +++ b/extractor/filesystem/language/wordpress/plugins/plugins.go @@ -126,7 +126,7 @@ func (e Extractor) reportFileRequired(path string, fileSizeBytes int64, result s } // Extract parses the PHP file to extract Wordpress package. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { pkg, err := parsePHPFile(input.Reader) if err != nil { return nil, err @@ -136,13 +136,11 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] return nil, nil } - inventory := &extractor.Inventory{ + return []*extractor.Package{&extractor.Package{ Name: pkg.Name, Version: pkg.Version, Locations: []string{input.Path}, - } - - return []*extractor.Inventory{inventory}, nil + }}, nil } type wpPackage struct { @@ -181,17 +179,17 @@ func parsePHPFile(r io.Reader) (*wpPackage, error) { return &wpPackage{Name: name, Version: version}, nil } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { return &purl.PackageURL{ Type: purl.TypeWordpress, - Name: i.Name, - Version: i.Version, + Name: p.Name, + Version: p.Version, } } // Ecosystem returns the OSV Ecosystem of the software extracted by this extractor. -func (e Extractor) Ecosystem(_ *extractor.Inventory) string { +func (e Extractor) Ecosystem(_ *extractor.Package) string { // wordpress ecosystem does not exist in OSV return "" } diff --git a/extractor/filesystem/language/wordpress/plugins/plugins_test.go b/extractor/filesystem/language/wordpress/plugins/plugins_test.go index 4bb3afcb..c2a98220 100644 --- a/extractor/filesystem/language/wordpress/plugins/plugins_test.go +++ b/extractor/filesystem/language/wordpress/plugins/plugins_test.go @@ -165,7 +165,7 @@ func TestExtract(t *testing.T) { InputConfig: extracttest.ScanInputMockConfig{ Path: "testdata/valid", }, - WantInventory: []*extractor.Inventory{ + WantPackages: []*extractor.Package{ { Name: "Akismet Anti-spam: Spam Protection", Version: "5.3", @@ -205,7 +205,7 @@ func TestExtract(t *testing.T) { return } - if diff := cmp.Diff(tt.WantInventory, got, cmpopts.SortSlices(extracttest.InventoryCmpLess)); diff != "" { + if diff := cmp.Diff(tt.WantPackages, got, cmpopts.SortSlices(extracttest.PackageCmpLess)); diff != "" { t.Errorf("%s.Extract(%q) diff (-want +got):\n%s", e.Name(), tt.InputConfig.Path, diff) } }) @@ -214,7 +214,7 @@ func TestExtract(t *testing.T) { func TestToPURL(t *testing.T) { e := plugins.Extractor{} - i := &extractor.Inventory{ + i := &extractor.Package{ Name: "Name", Version: "1.2.3", Locations: []string{"location"}, diff --git a/extractor/filesystem/os/apk/apk.go b/extractor/filesystem/os/apk/apk.go index 3149e76f..368a6408 100644 --- a/extractor/filesystem/os/apk/apk.go +++ b/extractor/filesystem/os/apk/apk.go @@ -116,8 +116,8 @@ func (e Extractor) reportFileRequired(path string, fileSizeBytes int64, result s } // Extract extracts packages from lib/apk/db/installed passed through the scan input. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { - inventory, err := e.extractFromInput(ctx, input) +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { + pkgs, err := e.extractFromInput(ctx, input) if e.stats != nil { var fileSizeBytes int64 if input.Info != nil { @@ -129,7 +129,7 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] FileSizeBytes: fileSizeBytes, }) } - return inventory, err + return pkgs, err } // parseSingleApkRecord reads from the scanner a single record, @@ -165,14 +165,14 @@ func parseSingleApkRecord(scanner *bufio.Scanner) (map[string]string, error) { return group, scanner.Err() } -func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { m, err := osrelease.GetOSRelease(input.FS) if err != nil { log.Errorf("osrelease.ParseOsRelease(): %v", err) } scanner := bufio.NewScanner(input.Reader) - inventories := []*extractor.Inventory{} + packages := []*extractor.Package{} for eof := false; !eof; { if err := ctx.Err(); err != nil { @@ -195,7 +195,7 @@ func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanI } } - var pkg = &extractor.Inventory{ + var pkg = &extractor.Package{ Name: record["P"], Version: record["V"], Metadata: &Metadata{ @@ -216,10 +216,10 @@ func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanI continue } - inventories = append(inventories, pkg) + packages = append(packages, pkg) } - return inventories, nil + return packages, nil } func toNamespace(m *Metadata) string { @@ -239,9 +239,9 @@ func toDistro(m *Metadata) string { return "" } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { - m := i.Metadata.(*Metadata) +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { + m := p.Metadata.(*Metadata) q := map[string]string{} distro := toDistro(m) if distro != "" { @@ -255,16 +255,16 @@ func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { } return &purl.PackageURL{ Type: purl.TypeApk, - Name: strings.ToLower(i.Name), + Name: strings.ToLower(p.Name), Namespace: toNamespace(m), - Version: i.Version, + Version: p.Version, Qualifiers: purl.QualifiersFromMap(q), } } // Ecosystem returns the OSV Ecosystem of the software extracted by this extractor. -func (Extractor) Ecosystem(i *extractor.Inventory) string { - version := toDistro(i.Metadata.(*Metadata)) +func (Extractor) Ecosystem(p *extractor.Package) string { + version := toDistro(p.Metadata.(*Metadata)) if version == "" { return "Alpine" } diff --git a/extractor/filesystem/os/apk/apk_test.go b/extractor/filesystem/os/apk/apk_test.go index 14029cbf..e69ba019 100644 --- a/extractor/filesystem/os/apk/apk_test.go +++ b/extractor/filesystem/os/apk/apk_test.go @@ -138,7 +138,7 @@ func TestExtract(t *testing.T) { name string path string osrelease string - wantInventory []*extractor.Inventory + wantPackages []*extractor.Package wantErr error wantResultMetric stats.FileExtractedResult }{ @@ -146,22 +146,22 @@ func TestExtract(t *testing.T) { name: "alpine latest", path: "testdata/installed", osrelease: alpine, - wantInventory: []*extractor.Inventory{ - getInventory("testdata/installed", "alpine-baselayout", "alpine-baselayout", "3.4.3-r1", "alpine", "3.18.0", "Natanael Copa ", "x86_64", "GPL-2.0-only", "65502ca9379dd29d1ac4b0bf0dcf03a3dd1b324a"), - getInventory("testdata/installed", "alpine-baselayout-data", "alpine-baselayout", "3.4.3-r1", "alpine", "3.18.0", "Natanael Copa ", "x86_64", "GPL-2.0-only", "65502ca9379dd29d1ac4b0bf0dcf03a3dd1b324a"), - getInventory("testdata/installed", "alpine-keys", "alpine-keys", "2.4-r1", "alpine", "3.18.0", "Natanael Copa ", "x86_64", "MIT", "aab68f8c9ab434a46710de8e12fb3206e2930a59"), - getInventory("testdata/installed", "apk-tools", "apk-tools", "2.14.0-r0", "alpine", "3.18.0", "Natanael Copa ", "x86_64", "GPL-2.0-only", "028d34f678a5386c3dc488cc3b62467c7a9d1a0b"), - getInventory("testdata/installed", "busybox", "busybox", "1.36.0-r9", "alpine", "3.18.0", "Sören Tempel ", "x86_64", "GPL-2.0-only", "b5c719c244319df3c72ab1f1ee994c2143cab7f0"), - getInventory("testdata/installed", "busybox-binsh", "busybox", "1.36.0-r9", "alpine", "3.18.0", "Sören Tempel ", "x86_64", "GPL-2.0-only", "b5c719c244319df3c72ab1f1ee994c2143cab7f0"), - getInventory("testdata/installed", "ca-certificates-bundle", "ca-certificates", "20230506-r0", "alpine", "3.18.0", "Natanael Copa ", "x86_64", "MPL-2.0 AND MIT", "59534a02716a92a10d177a118c34066162eff4a6"), - getInventory("testdata/installed", "libc-utils", "libc-dev", "0.7.2-r5", "alpine", "3.18.0", "Natanael Copa ", "x86_64", "BSD-2-Clause AND BSD-3-Clause", "988f183cc9d6699930c3e18ccf4a9e36010afb56"), - getInventory("testdata/installed", "libcrypto3", "openssl", "3.1.0-r4", "alpine", "3.18.0", "Ariadne Conill ", "x86_64", "Apache-2.0", "730b75e01c670e3dba5d6c05420b5f605edb6201"), - getInventory("testdata/installed", "libssl3", "openssl", "3.1.0-r4", "alpine", "3.18.0", "Ariadne Conill ", "x86_64", "Apache-2.0", "730b75e01c670e3dba5d6c05420b5f605edb6201"), - getInventory("testdata/installed", "musl", "musl", "1.2.4-r0", "alpine", "3.18.0", "Timo Teräs ", "x86_64", "MIT", "b0d8a9d948174e28a4aefcee4ef6be872225ccce"), - getInventory("testdata/installed", "musl-utils", "musl", "1.2.4-r0", "alpine", "3.18.0", "Timo Teräs ", "x86_64", "MIT AND BSD-2-Clause AND GPL-2.0-or-later", "b0d8a9d948174e28a4aefcee4ef6be872225ccce"), - getInventory("testdata/installed", "scanelf", "pax-utils", "1.3.7-r1", "alpine", "3.18.0", "Natanael Copa ", "x86_64", "GPL-2.0-only", "84a227baf001b6e0208e3352b294e4d7a40e93de"), - getInventory("testdata/installed", "ssl_client", "busybox", "1.36.0-r9", "alpine", "3.18.0", "Sören Tempel ", "x86_64", "GPL-2.0-only", "b5c719c244319df3c72ab1f1ee994c2143cab7f0"), - getInventory("testdata/installed", "zlib", "zlib", "1.2.13-r1", "alpine", "3.18.0", "Natanael Copa ", "x86_64", "Zlib", "84a227baf001b6e0208e3352b294e4d7a40e93de"), + wantPackages: []*extractor.Package{ + getPackage("testdata/installed", "alpine-baselayout", "alpine-baselayout", "3.4.3-r1", "alpine", "3.18.0", "Natanael Copa ", "x86_64", "GPL-2.0-only", "65502ca9379dd29d1ac4b0bf0dcf03a3dd1b324a"), + getPackage("testdata/installed", "alpine-baselayout-data", "alpine-baselayout", "3.4.3-r1", "alpine", "3.18.0", "Natanael Copa ", "x86_64", "GPL-2.0-only", "65502ca9379dd29d1ac4b0bf0dcf03a3dd1b324a"), + getPackage("testdata/installed", "alpine-keys", "alpine-keys", "2.4-r1", "alpine", "3.18.0", "Natanael Copa ", "x86_64", "MIT", "aab68f8c9ab434a46710de8e12fb3206e2930a59"), + getPackage("testdata/installed", "apk-tools", "apk-tools", "2.14.0-r0", "alpine", "3.18.0", "Natanael Copa ", "x86_64", "GPL-2.0-only", "028d34f678a5386c3dc488cc3b62467c7a9d1a0b"), + getPackage("testdata/installed", "busybox", "busybox", "1.36.0-r9", "alpine", "3.18.0", "Sören Tempel ", "x86_64", "GPL-2.0-only", "b5c719c244319df3c72ab1f1ee994c2143cab7f0"), + getPackage("testdata/installed", "busybox-binsh", "busybox", "1.36.0-r9", "alpine", "3.18.0", "Sören Tempel ", "x86_64", "GPL-2.0-only", "b5c719c244319df3c72ab1f1ee994c2143cab7f0"), + getPackage("testdata/installed", "ca-certificates-bundle", "ca-certificates", "20230506-r0", "alpine", "3.18.0", "Natanael Copa ", "x86_64", "MPL-2.0 AND MIT", "59534a02716a92a10d177a118c34066162eff4a6"), + getPackage("testdata/installed", "libc-utils", "libc-dev", "0.7.2-r5", "alpine", "3.18.0", "Natanael Copa ", "x86_64", "BSD-2-Clause AND BSD-3-Clause", "988f183cc9d6699930c3e18ccf4a9e36010afb56"), + getPackage("testdata/installed", "libcrypto3", "openssl", "3.1.0-r4", "alpine", "3.18.0", "Ariadne Conill ", "x86_64", "Apache-2.0", "730b75e01c670e3dba5d6c05420b5f605edb6201"), + getPackage("testdata/installed", "libssl3", "openssl", "3.1.0-r4", "alpine", "3.18.0", "Ariadne Conill ", "x86_64", "Apache-2.0", "730b75e01c670e3dba5d6c05420b5f605edb6201"), + getPackage("testdata/installed", "musl", "musl", "1.2.4-r0", "alpine", "3.18.0", "Timo Teräs ", "x86_64", "MIT", "b0d8a9d948174e28a4aefcee4ef6be872225ccce"), + getPackage("testdata/installed", "musl-utils", "musl", "1.2.4-r0", "alpine", "3.18.0", "Timo Teräs ", "x86_64", "MIT AND BSD-2-Clause AND GPL-2.0-or-later", "b0d8a9d948174e28a4aefcee4ef6be872225ccce"), + getPackage("testdata/installed", "scanelf", "pax-utils", "1.3.7-r1", "alpine", "3.18.0", "Natanael Copa ", "x86_64", "GPL-2.0-only", "84a227baf001b6e0208e3352b294e4d7a40e93de"), + getPackage("testdata/installed", "ssl_client", "busybox", "1.36.0-r9", "alpine", "3.18.0", "Sören Tempel ", "x86_64", "GPL-2.0-only", "b5c719c244319df3c72ab1f1ee994c2143cab7f0"), + getPackage("testdata/installed", "zlib", "zlib", "1.2.13-r1", "alpine", "3.18.0", "Natanael Copa ", "x86_64", "Zlib", "84a227baf001b6e0208e3352b294e4d7a40e93de"), }, wantResultMetric: stats.FileExtractedResultSuccess, }, @@ -169,21 +169,21 @@ func TestExtract(t *testing.T) { name: "origin not set", path: "testdata/no-origin", osrelease: alpine, - wantInventory: []*extractor.Inventory{ - getInventory("testdata/no-origin", "pkgname", "", "1.2.3", "alpine", "3.18.0", "", "x86_64", "GPL-2.0-only", ""), + wantPackages: []*extractor.Package{ + getPackage("testdata/no-origin", "pkgname", "", "1.2.3", "alpine", "3.18.0", "", "x86_64", "GPL-2.0-only", ""), }, wantResultMetric: stats.FileExtractedResultSuccess, }, { name: "empty", path: "testdata/empty", - wantInventory: []*extractor.Inventory{}, + wantPackages: []*extractor.Package{}, wantResultMetric: stats.FileExtractedResultSuccess, }, { name: "invalid", path: "testdata/invalid", - wantInventory: nil, + wantPackages: nil, wantErr: cmpopts.AnyError, wantResultMetric: stats.FileExtractedResultErrorUnknown, }, @@ -192,8 +192,8 @@ func TestExtract(t *testing.T) { path: "testdata/single", osrelease: `ID=openwrt VERSION_ID=1.2.3`, - wantInventory: []*extractor.Inventory{ - getInventory("testdata/single", "alpine-baselayout-data", "alpine-baselayout", "3.4.3-r1", "openwrt", "1.2.3", "Natanael Copa ", "x86_64", "GPL-2.0-only", "65502ca9379dd29d1ac4b0bf0dcf03a3dd1b324a"), + wantPackages: []*extractor.Package{ + getPackage("testdata/single", "alpine-baselayout-data", "alpine-baselayout", "3.4.3-r1", "openwrt", "1.2.3", "Natanael Copa ", "x86_64", "GPL-2.0-only", "65502ca9379dd29d1ac4b0bf0dcf03a3dd1b324a"), }, wantResultMetric: stats.FileExtractedResultSuccess, }, @@ -201,8 +201,8 @@ func TestExtract(t *testing.T) { name: "osrelease no version", path: "testdata/single", osrelease: "ID=openwrt", - wantInventory: []*extractor.Inventory{ - getInventory("testdata/single", "alpine-baselayout-data", "alpine-baselayout", "3.4.3-r1", "openwrt", "", "Natanael Copa ", "x86_64", "GPL-2.0-only", "65502ca9379dd29d1ac4b0bf0dcf03a3dd1b324a"), + wantPackages: []*extractor.Package{ + getPackage("testdata/single", "alpine-baselayout-data", "alpine-baselayout", "3.4.3-r1", "openwrt", "", "Natanael Copa ", "x86_64", "GPL-2.0-only", "65502ca9379dd29d1ac4b0bf0dcf03a3dd1b324a"), }, wantResultMetric: stats.FileExtractedResultSuccess, }, @@ -210,8 +210,8 @@ func TestExtract(t *testing.T) { name: "no osrelease", path: "testdata/single", osrelease: "", - wantInventory: []*extractor.Inventory{ - getInventory("testdata/single", "alpine-baselayout-data", "alpine-baselayout", "3.4.3-r1", "", "", "Natanael Copa ", "x86_64", "GPL-2.0-only", "65502ca9379dd29d1ac4b0bf0dcf03a3dd1b324a"), + wantPackages: []*extractor.Package{ + getPackage("testdata/single", "alpine-baselayout-data", "alpine-baselayout", "3.4.3-r1", "", "", "Natanael Copa ", "x86_64", "GPL-2.0-only", "65502ca9379dd29d1ac4b0bf0dcf03a3dd1b324a"), }, wantResultMetric: stats.FileExtractedResultSuccess, }, @@ -219,8 +219,8 @@ func TestExtract(t *testing.T) { name: "different arch", path: "testdata/different-arch", osrelease: "", - wantInventory: []*extractor.Inventory{ - getInventory("testdata/different-arch", "alpine-baselayout-data", "alpine-baselayout", "3.4.3-r1", "", "", "Natanael Copa ", "noarch", "GPL-2.0-only", "65502ca9379dd29d1ac4b0bf0dcf03a3dd1b324a"), + wantPackages: []*extractor.Package{ + getPackage("testdata/different-arch", "alpine-baselayout-data", "alpine-baselayout", "3.4.3-r1", "", "", "Natanael Copa ", "noarch", "GPL-2.0-only", "65502ca9379dd29d1ac4b0bf0dcf03a3dd1b324a"), }, wantResultMetric: stats.FileExtractedResultSuccess, }, @@ -267,7 +267,7 @@ func TestExtract(t *testing.T) { ignoreOrder := cmpopts.SortSlices(func(a, b any) bool { return fmt.Sprintf("%+v", a) < fmt.Sprintf("%+v", b) }) - if diff := cmp.Diff(tt.wantInventory, got, ignoreOrder); diff != "" { + if diff := cmp.Diff(tt.wantPackages, got, ignoreOrder); diff != "" { t.Errorf("Extract(%s) (-want +got):\n%s", tt.path, diff) } @@ -340,15 +340,15 @@ func TestToPURL(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - i := &extractor.Inventory{ + p := &extractor.Package{ Name: "Name", Version: "1.2.3", Metadata: tt.metadata, Locations: []string{"location"}, } - got := e.ToPURL(i) + got := e.ToPURL(p) if diff := cmp.Diff(tt.want, got); diff != "" { - t.Errorf("ToPURL(%v) (-want +got):\n%s", i, diff) + t.Errorf("ToPURL(%v) (-want +got):\n%s", p, diff) } }) } @@ -383,22 +383,22 @@ func TestEcosystem(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - i := &extractor.Inventory{ + p := &extractor.Package{ Name: "Name", Version: "1.2.3", Metadata: tt.metadata, Locations: []string{"location"}, } - got := e.Ecosystem(i) + got := e.Ecosystem(p) if diff := cmp.Diff(tt.want, got); diff != "" { - t.Errorf("Ecosystem(%v) (-want +got):\n%s", i, diff) + t.Errorf("Ecosystem(%v) (-want +got):\n%s", p, diff) } }) } } -func getInventory(path, pkgName, origin, version, osID, osVersionID, maintainer, arch, license string, commit string) *extractor.Inventory { - i := &extractor.Inventory{ +func getPackage(path, pkgName, origin, version, osID, osVersionID, maintainer, arch, license string, commit string) *extractor.Package { + p := &extractor.Package{ Locations: []string{path}, Name: pkgName, Version: version, @@ -413,11 +413,11 @@ func getInventory(path, pkgName, origin, version, osID, osVersionID, maintainer, }, } if commit != "" { - i.SourceCode = &extractor.SourceCodeIdentifier{ + p.SourceCode = &extractor.SourceCodeIdentifier{ Commit: commit, } } - return i + return p } func createOsRelease(t *testing.T, root string, content string) { diff --git a/extractor/filesystem/os/cos/cos.go b/extractor/filesystem/os/cos/cos.go index 26e6b9c9..84806f92 100644 --- a/extractor/filesystem/os/cos/cos.go +++ b/extractor/filesystem/os/cos/cos.go @@ -129,8 +129,8 @@ func (e Extractor) reportFileRequired(path string, fileSizeBytes int64, result s } // Extract extracts packages from cos package info files passed through the scan input. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { - inventory, err := e.extractFromInput(ctx, input) +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { + pkgs, err := e.extractFromInput(ctx, input) if e.stats != nil { var fileSizeBytes int64 if input.Info != nil { @@ -142,10 +142,10 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] FileSizeBytes: fileSizeBytes, }) } - return inventory, err + return pkgs, err } -func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { m, err := osrelease.GetOSRelease(input.FS) if err != nil { log.Errorf("osrelease.ParseOsRelease(): %v", err) @@ -162,9 +162,9 @@ func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanI log.Infof("Found %d installed packages", len(packages.InstalledPackages)) log.Infof("Found %d build time packages", len(packages.BuildTimePackages)) - inventory := []*extractor.Inventory{} + pkgs := []*extractor.Package{} for _, pkg := range packages.InstalledPackages { - i := &extractor.Inventory{ + pkgs = append(pkgs, &extractor.Package{ Name: pkg.Name, Version: pkg.Version, Metadata: &Metadata{ @@ -176,11 +176,10 @@ func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanI EbuildVersion: pkg.EbuildVersion, }, Locations: []string{input.Path}, - } - inventory = append(inventory, i) + }) } - return inventory, nil + return pkgs, nil } func toDistro(m *Metadata) string { @@ -196,9 +195,9 @@ func toDistro(m *Metadata) string { return "" } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { - m := i.Metadata.(*Metadata) +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { + m := p.Metadata.(*Metadata) q := map[string]string{} distro := toDistro(m) if distro != "" { @@ -206,11 +205,11 @@ func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { } return &purl.PackageURL{ Type: purl.TypeCOS, - Name: i.Name, - Version: i.Version, + Name: p.Name, + Version: p.Version, Qualifiers: purl.QualifiersFromMap(q), } } // Ecosystem returns no Ecosystem since the ecosystem is not known by OSV yet. -func (e Extractor) Ecosystem(i *extractor.Inventory) string { return "" } +func (e Extractor) Ecosystem(p *extractor.Package) string { return "" } diff --git a/extractor/filesystem/os/cos/cos_test.go b/extractor/filesystem/os/cos/cos_test.go index 7299d7ad..084c897e 100644 --- a/extractor/filesystem/os/cos/cos_test.go +++ b/extractor/filesystem/os/cos/cos_test.go @@ -133,7 +133,7 @@ func TestExtract(t *testing.T) { name string path string osrelease string - wantInventory []*extractor.Inventory + wantPackages []*extractor.Package wantErr error wantResultMetric stats.FileExtractedResult }{ @@ -148,14 +148,14 @@ func TestExtract(t *testing.T) { name: "empty", path: "testdata/empty.json", osrelease: cosOSRlease, - wantInventory: []*extractor.Inventory{}, + wantPackages: []*extractor.Package{}, wantResultMetric: stats.FileExtractedResultSuccess, }, { name: "single", path: "testdata/single.json", osrelease: cosOSRlease, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "python-exec", Version: "17162.336.16", @@ -176,7 +176,7 @@ func TestExtract(t *testing.T) { name: "multiple", path: "testdata/multiple.json", osrelease: cosOSRlease, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "python-exec", Version: "17162.336.16", @@ -236,7 +236,7 @@ func TestExtract(t *testing.T) { name: "no version ID", path: "testdata/single.json", osrelease: cosOSRleaseNoVersionID, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "python-exec", Version: "17162.336.16", @@ -255,7 +255,7 @@ func TestExtract(t *testing.T) { name: "no version or version ID", path: "testdata/single.json", osrelease: cosOSRleaseNoVersions, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "python-exec", Version: "17162.336.16", @@ -313,7 +313,7 @@ func TestExtract(t *testing.T) { ignoreOrder := cmpopts.SortSlices(func(a, b any) bool { return fmt.Sprintf("%+v", a) < fmt.Sprintf("%+v", b) }) - if diff := cmp.Diff(tt.wantInventory, got, ignoreOrder); diff != "" { + if diff := cmp.Diff(tt.wantPackages, got, ignoreOrder); diff != "" { t.Errorf("Extract(%s) (-want +got):\n%s", tt.path, diff) } @@ -387,15 +387,15 @@ func TestToPURL(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - i := &extractor.Inventory{ + p := &extractor.Package{ Name: "name", Version: "1.2.3", Metadata: tt.metadata, Locations: []string{"location"}, } - got := e.ToPURL(i) + got := e.ToPURL(p) if diff := cmp.Diff(tt.want, got); diff != "" { - t.Errorf("ToPURL(%v) (-want +got):\n%s", i, diff) + t.Errorf("ToPURL(%v) (-want +got):\n%s", p, diff) } }) } diff --git a/extractor/filesystem/os/dpkg/dpkg.go b/extractor/filesystem/os/dpkg/dpkg.go index 559948b5..4cbf5846 100644 --- a/extractor/filesystem/os/dpkg/dpkg.go +++ b/extractor/filesystem/os/dpkg/dpkg.go @@ -155,8 +155,8 @@ func (e Extractor) reportFileRequired(path string, fileSizeBytes int64, result s } // Extract extracts packages from dpkg status files passed through the scan input. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { - inventory, err := e.extractFromInput(ctx, input) +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { + pkgs, err := e.extractFromInput(ctx, input) if e.stats != nil { var fileSizeBytes int64 if input.Info != nil { @@ -168,17 +168,17 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] FileSizeBytes: fileSizeBytes, }) } - return inventory, err + return pkgs, err } -func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { m, err := osrelease.GetOSRelease(input.FS) if err != nil { log.Errorf("osrelease.ParseOsRelease(): %v", err) } rd := textproto.NewReader(bufio.NewReader(input.Reader)) - pkgs := []*extractor.Inventory{} + pkgs := []*extractor.Package{} for eof := false; !eof; { // Return if canceled or exceeding deadline. if err := ctx.Err(); err != nil { @@ -194,7 +194,7 @@ func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanI } else { if strings.Contains(input.Path, "status.d") { log.Warnf("Failed to read MIME header from %q: %v", input.Path, err) - return []*extractor.Inventory{}, nil + return []*extractor.Package{}, nil } return pkgs, err } @@ -238,7 +238,7 @@ func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanI annotations = append(annotations, extractor.Transitional) } - i := &extractor.Inventory{ + p := &extractor.Package{ Name: pkgName, Version: pkgVersion, Metadata: &Metadata{ @@ -259,11 +259,11 @@ func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanI return pkgs, fmt.Errorf("parseSourceNameVersion(%q): %w", h.Get("Source"), err) } if sourceName != "" { - i.Metadata.(*Metadata).SourceName = sourceName - i.Metadata.(*Metadata).SourceVersion = sourceVersion + p.Metadata.(*Metadata).SourceName = sourceName + p.Metadata.(*Metadata).SourceVersion = sourceVersion } - pkgs = append(pkgs, i) + pkgs = append(pkgs, p) } return pkgs, nil } @@ -318,9 +318,9 @@ func toDistro(m *Metadata) string { return "" } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { - m := i.Metadata.(*Metadata) +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { + m := p.Metadata.(*Metadata) q := map[string]string{} distro := toDistro(m) if distro != "" { @@ -339,7 +339,7 @@ func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { // Determine the package type (opkg or dpkg) based on file location typePurl := "" - for _, location := range i.Locations { + for _, location := range p.Locations { if location == "usr/lib/opkg/status" { typePurl = purl.TypeOpkg break @@ -355,14 +355,14 @@ func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { Type: typePurl, Name: m.PackageName, Namespace: toNamespace(m), - Version: i.Version, + Version: p.Version, Qualifiers: purl.QualifiersFromMap(q), } } // Ecosystem returns the OSV Ecosystem of the software extracted by this extractor. -func (Extractor) Ecosystem(i *extractor.Inventory) string { - m := i.Metadata.(*Metadata) +func (Extractor) Ecosystem(p *extractor.Package) string { + m := p.Metadata.(*Metadata) osID := cases.Title(language.English).String(toNamespace(m)) if m.OSVersionID == "" { return osID diff --git a/extractor/filesystem/os/dpkg/dpkg_test.go b/extractor/filesystem/os/dpkg/dpkg_test.go index cdac0692..43f4f6d0 100644 --- a/extractor/filesystem/os/dpkg/dpkg_test.go +++ b/extractor/filesystem/os/dpkg/dpkg_test.go @@ -205,7 +205,7 @@ func TestExtract(t *testing.T) { path string osrelease string cfg dpkg.Config - wantInventory []*extractor.Inventory + wantPackages []*extractor.Package wantErr error wantResultMetric stats.FileExtractedResult wantLogWarn int @@ -215,7 +215,7 @@ func TestExtract(t *testing.T) { name: "valid status file", path: "testdata/dpkg/valid", osrelease: DebianBookworm, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "accountsservice", Version: "22.08.8-6", @@ -333,7 +333,7 @@ func TestExtract(t *testing.T) { name: "packages with no version set are skipped", path: "testdata/dpkg/noversion", osrelease: DebianBookworm, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "foo", Version: "1.0", @@ -368,7 +368,7 @@ func TestExtract(t *testing.T) { name: "packages with no name set are skipped", path: "testdata/dpkg/nopackage", osrelease: DebianBookworm, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "foo", Version: "1.0", @@ -403,7 +403,7 @@ func TestExtract(t *testing.T) { name: "statusfield", path: "testdata/dpkg/statusfield", osrelease: DebianBookworm, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "wantinstall_installed", Version: "1.0", @@ -454,7 +454,7 @@ func TestExtract(t *testing.T) { cfg: dpkg.Config{ IncludeNotInstalled: true, }, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "wantinstall_installed", Version: "1.0", @@ -552,14 +552,14 @@ func TestExtract(t *testing.T) { name: "empty", path: "testdata/dpkg/empty", osrelease: DebianBookworm, - wantInventory: []*extractor.Inventory{}, + wantPackages: []*extractor.Package{}, wantResultMetric: stats.FileExtractedResultSuccess, }, { name: "invalid", path: "testdata/dpkg/invalid", osrelease: DebianBookworm, - wantInventory: []*extractor.Inventory{}, + wantPackages: []*extractor.Package{}, wantErr: cmpopts.AnyError, wantResultMetric: stats.FileExtractedResultErrorUnknown, }, @@ -568,7 +568,7 @@ func TestExtract(t *testing.T) { path: "testdata/dpkg/single", osrelease: `VERSION_ID="12" ID=debian`, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "acl", Version: "2.3.1-3", @@ -590,7 +590,7 @@ func TestExtract(t *testing.T) { name: "no version", path: "testdata/dpkg/single", osrelease: `ID=debian`, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "acl", Version: "2.3.1-3", @@ -611,7 +611,7 @@ func TestExtract(t *testing.T) { name: "osrelease id not set", path: "testdata/dpkg/single", osrelease: "VERSION_CODENAME=bookworm", - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "acl", Version: "2.3.1-3", @@ -635,7 +635,7 @@ func TestExtract(t *testing.T) { VERSION_CODENAME=jammy ID=ubuntu ID_LIKE=debian`, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "acl", Version: "2.3.1-3", @@ -661,7 +661,7 @@ func TestExtract(t *testing.T) { VERSION_CODENAME=jammy ID=ubuntu ID_LIKE=debian`, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "acl", Version: "2.3.1-3", @@ -686,7 +686,7 @@ func TestExtract(t *testing.T) { name: "status.d file without Status field set should work", path: "testdata/dpkg/status.d/foo", osrelease: DebianBookworm, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "foo", Version: "1.2.3", @@ -708,7 +708,7 @@ func TestExtract(t *testing.T) { name: "status.d file without Status field set should work", path: "testdata/dpkg/status.d/foo.md5sums", osrelease: DebianBookworm, - wantInventory: []*extractor.Inventory{}, + wantPackages: []*extractor.Package{}, wantResultMetric: stats.FileExtractedResultSuccess, wantLogWarn: 1, }, @@ -716,7 +716,7 @@ func TestExtract(t *testing.T) { name: "transitional packages should be annotated", path: "testdata/dpkg/transitional", osrelease: DebianBookworm, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "iceweasel", Version: "78.13.0esr-1~deb10u1", @@ -741,7 +741,7 @@ func TestExtract(t *testing.T) { name: "transitional dummy packages should be annotated", path: "testdata/dpkg/transitional_dummy", osrelease: DebianBookworm, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "git-core", Version: "1:2.14.2-1", @@ -766,7 +766,7 @@ func TestExtract(t *testing.T) { name: "transitional empty packages should be annotated", path: "testdata/dpkg/transitional_empty", osrelease: DebianBookworm, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "runit-systemd", Version: "2.1.2-54+usrmerge", @@ -791,7 +791,7 @@ func TestExtract(t *testing.T) { name: "valid opkg status file", path: "testdata/opkg/valid", // Path to your OPKG status file in the test data osrelease: OpkgRelease, // You can mock the os-release data as needed - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "ubus", Version: "2024.10.20~252a9b0c-r1", @@ -841,7 +841,7 @@ func TestExtract(t *testing.T) { name: "packages with no version set are skipped", path: "testdata/opkg/noversion", osrelease: OpkgRelease, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "ubus", Version: "2024.10.20~252a9b0c-r1", @@ -878,7 +878,7 @@ func TestExtract(t *testing.T) { name: "packages with no name set are skipped", path: "testdata/opkg/nopackage", osrelease: OpkgRelease, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "ubus", Version: "2024.10.20~252a9b0c-r1", @@ -915,7 +915,7 @@ func TestExtract(t *testing.T) { name: "statusfield", path: "testdata/opkg/statusfield", // Path to your OPKG status file in the test data osrelease: OpkgRelease, // You can mock the os-release data as needed - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "wantinstall_installed", Version: "1.0", @@ -953,7 +953,7 @@ func TestExtract(t *testing.T) { cfg: dpkg.Config{ IncludeNotInstalled: true, }, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "wantinstall_installed", Version: "1.0", @@ -1038,14 +1038,14 @@ func TestExtract(t *testing.T) { name: "empty", path: "testdata/opkg/empty", osrelease: OpkgRelease, - wantInventory: []*extractor.Inventory{}, + wantPackages: []*extractor.Package{}, wantResultMetric: stats.FileExtractedResultSuccess, }, { name: "invalid", path: "testdata/opkg/invalid", osrelease: OpkgRelease, - wantInventory: []*extractor.Inventory{}, + wantPackages: []*extractor.Package{}, wantErr: cmpopts.AnyError, wantResultMetric: stats.FileExtractedResultErrorUnknown, }, @@ -1054,7 +1054,7 @@ func TestExtract(t *testing.T) { path: "testdata/opkg/single", osrelease: `VERSION_ID="21.02.1" ID=openwrt`, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "ubus", Version: "2024.10.20~252a9b0c-r1", @@ -1075,7 +1075,7 @@ func TestExtract(t *testing.T) { name: "no version", path: "testdata/opkg/single", osrelease: `ID=openwrt`, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "ubus", Version: "2024.10.20~252a9b0c-r1", @@ -1095,7 +1095,7 @@ func TestExtract(t *testing.T) { name: "osrelease id not set", path: "testdata/opkg/single", osrelease: `VERSION_CODENAME=openwrt-21.02.1`, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "ubus", Version: "2024.10.20~252a9b0c-r1", @@ -1115,7 +1115,7 @@ func TestExtract(t *testing.T) { name: "newlines", path: "testdata/opkg/trailingnewlines", osrelease: OpkgRelease, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "ubus", Version: "2024.10.20~252a9b0c-r1", @@ -1139,7 +1139,7 @@ func TestExtract(t *testing.T) { name: "transitional packages should be annotated", path: "testdata/opkg/transitional", osrelease: OpkgRelease, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "ubus", Version: "2024.10.20~252a9b0c-r1", @@ -1200,7 +1200,7 @@ func TestExtract(t *testing.T) { ignoreOrder := cmpopts.SortSlices(func(a, b any) bool { return fmt.Sprintf("%+v", a) < fmt.Sprintf("%+v", b) }) - if diff := cmp.Diff(tt.wantInventory, got, ignoreOrder); diff != "" { + if diff := cmp.Diff(tt.wantPackages, got, ignoreOrder); diff != "" { t.Errorf("Extract(%s) (-want +got):\n%s", tt.path, diff) } @@ -1283,7 +1283,7 @@ func (l *testLogger) Debug(args ...any) { func TestExtractNonexistentOSRelease(t *testing.T) { path := "testdata/dpkg/single" - want := []*extractor.Inventory{ + want := []*extractor.Package{ { Name: "acl", Version: "2.3.1-3", @@ -1446,15 +1446,15 @@ func TestToPURL(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - i := &extractor.Inventory{ + p := &extractor.Package{ Name: pkgname, Version: version, Metadata: tt.metadata, Locations: []string{tt.location}, } - got := e.ToPURL(i) + got := e.ToPURL(p) if diff := cmp.Diff(tt.want, got); diff != "" { - t.Errorf("ToPURL(%v) (-want +got):\n%s", i, diff) + t.Errorf("ToPURL(%v) (-want +got):\n%s", p, diff) } }) } @@ -1513,12 +1513,12 @@ func TestEcosystem(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - i := &extractor.Inventory{ + p := &extractor.Package{ Metadata: tt.metadata, } - got := e.Ecosystem(i) + got := e.Ecosystem(p) if diff := cmp.Diff(tt.want, got); diff != "" { - t.Errorf("Ecosystem(%v) (-want +got):\n%s", i, diff) + t.Errorf("Ecosystem(%v) (-want +got):\n%s", p, diff) } }) } diff --git a/extractor/filesystem/os/flatpak/flatpak.go b/extractor/filesystem/os/flatpak/flatpak.go index 0deca33c..aa6dcf13 100644 --- a/extractor/filesystem/os/flatpak/flatpak.go +++ b/extractor/filesystem/os/flatpak/flatpak.go @@ -147,8 +147,8 @@ func (e Extractor) reportFileRequired(path string, fileSizeBytes int64, result s } // Extract extracts packages from metainfo xml files passed through the scan input. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { - i, err := e.extractFromInput(input) +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { + p, err := e.extractFromInput(input) if e.stats != nil { var fileSizeBytes int64 if input.Info != nil { @@ -163,13 +163,13 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] if err != nil { return nil, fmt.Errorf("flatpak.extract(%s): %w", input.Path, err) } - if i == nil { - return []*extractor.Inventory{}, nil + if p == nil { + return []*extractor.Package{}, nil } - return []*extractor.Inventory{i}, nil + return []*extractor.Package{p}, nil } -func (e Extractor) extractFromInput(input *filesystem.ScanInput) (*extractor.Inventory, error) { +func (e Extractor) extractFromInput(input *filesystem.ScanInput) (*extractor.Package, error) { m, err := osrelease.GetOSRelease(input.FS) if err != nil { log.Errorf("osrelease.ParseOsRelease(): %v", err) @@ -194,7 +194,7 @@ func (e Extractor) extractFromInput(input *filesystem.ScanInput) (*extractor.Inv return nil, fmt.Errorf("PackageVersion: %v does not exist", pkgVersion) } - i := &extractor.Inventory{ + p := &extractor.Package{ Name: f.ID, Version: pkgVersion, Metadata: &Metadata{ @@ -211,7 +211,7 @@ func (e Extractor) extractFromInput(input *filesystem.ScanInput) (*extractor.Inv Locations: []string{input.Path}, } - return i, nil + return p, nil } func toNamespace(m *Metadata) string { @@ -241,9 +241,9 @@ func toDistro(m *Metadata) string { return fmt.Sprintf("%s-%s", id, v) } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { - m := i.Metadata.(*Metadata) +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { + m := p.Metadata.(*Metadata) q := map[string]string{} distro := toDistro(m) if distro != "" { @@ -252,11 +252,11 @@ func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { return &purl.PackageURL{ Type: purl.TypeFlatpak, Namespace: toNamespace(m), - Name: i.Name, - Version: i.Version, + Name: p.Name, + Version: p.Version, Qualifiers: purl.QualifiersFromMap(q), } } // Ecosystem returns no Ecosystem since the ecosystem is not known by OSV yet. -func (e Extractor) Ecosystem(i *extractor.Inventory) string { return "" } +func (e Extractor) Ecosystem(p *extractor.Package) string { return "" } diff --git a/extractor/filesystem/os/flatpak/flatpak_test.go b/extractor/filesystem/os/flatpak/flatpak_test.go index 39616c79..f6b3011a 100644 --- a/extractor/filesystem/os/flatpak/flatpak_test.go +++ b/extractor/filesystem/os/flatpak/flatpak_test.go @@ -146,7 +146,7 @@ func TestExtract(t *testing.T) { path string osrelease string cfg flatpak.Config - wantInventory []*extractor.Inventory + wantPackages []*extractor.Package wantErr error wantResultMetric stats.FileExtractedResult }{ @@ -154,7 +154,7 @@ func TestExtract(t *testing.T) { name: "valid metainfo xml file is extracted", path: "testdata/valid.xml", osrelease: DebianBookworm, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "org.gimp.GIMP", Version: "2.10.38", @@ -177,7 +177,7 @@ func TestExtract(t *testing.T) { name: "metainfo xml file without package name is extracted", path: "testdata/noname.xml", osrelease: DebianBookworm, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "org.gimp.GIMP", Version: "2.10.38", @@ -247,7 +247,7 @@ func TestExtract(t *testing.T) { ignoreOrder := cmpopts.SortSlices(func(a, b any) bool { return fmt.Sprintf("%+v", a) < fmt.Sprintf("%+v", b) }) - if diff := cmp.Diff(tt.wantInventory, got, ignoreOrder); diff != "" { + if diff := cmp.Diff(tt.wantPackages, got, ignoreOrder); diff != "" { t.Errorf("Extract(%s) (-want +got):\n%s", tt.path, diff) } @@ -350,15 +350,15 @@ func TestToPURL(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - i := &extractor.Inventory{ + p := &extractor.Package{ Name: pkgname, Version: pkgversion, Metadata: tt.metadata, Locations: []string{"location"}, } - got := e.ToPURL(i) + got := e.ToPURL(p) if diff := cmp.Diff(tt.want, got); diff != "" { - t.Errorf("ToPURL(%v) (-want +got):\n%s", i, diff) + t.Errorf("ToPURL(%v) (-want +got):\n%s", p, diff) } }) } diff --git a/extractor/filesystem/os/homebrew/homebrew.go b/extractor/filesystem/os/homebrew/homebrew.go index 8b914029..2518daf3 100644 --- a/extractor/filesystem/os/homebrew/homebrew.go +++ b/extractor/filesystem/os/homebrew/homebrew.go @@ -93,12 +93,12 @@ func isCaskroom(filePath string) bool { } // Extract parses the recognised Homebrew file path and returns information about the installed package. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { p := SplitPath(input.Path) if p == nil { - return []*extractor.Inventory{}, nil + return []*extractor.Package{}, nil } - return []*extractor.Inventory{ + return []*extractor.Package{ { Name: p.AppName, Version: p.AppVersion, @@ -126,14 +126,14 @@ func SplitPath(path string) *BrewPath { return nil } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { return &purl.PackageURL{ Type: purl.TypeBrew, - Name: i.Name, - Version: i.Version, + Name: p.Name, + Version: p.Version, } } // Ecosystem returns no Ecosystem since the ecosystem is not known by OSV yet. -func (Extractor) Ecosystem(i *extractor.Inventory) string { return "" } +func (Extractor) Ecosystem(p *extractor.Package) string { return "" } diff --git a/extractor/filesystem/os/homebrew/homebrew_test.go b/extractor/filesystem/os/homebrew/homebrew_test.go index 52a50908..9406b4bb 100644 --- a/extractor/filesystem/os/homebrew/homebrew_test.go +++ b/extractor/filesystem/os/homebrew/homebrew_test.go @@ -105,21 +105,21 @@ func TestFileRequired(t *testing.T) { } } -func invLess(i1, i2 *extractor.Inventory) bool { +func pkgLess(i1, i2 *extractor.Package) bool { return i1.Name < i2.Name } func TestExtract(t *testing.T) { tests := []struct { - name string - path string - wantErr error - wantInventory []*extractor.Inventory + name string + path string + wantErr error + wantPackages []*extractor.Package }{ { name: "cellar.valid.json", path: "testdata/Cellar/rclone/1.67.0/INSTALL_RECEIPT.json", - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "rclone", Version: "1.67.0", @@ -131,7 +131,7 @@ func TestExtract(t *testing.T) { { name: "caskroom.valid.json", path: "testdata/Caskroom/testapp/1.1.1/testapp.wrapper.sh", - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "testapp", Version: "1.1.1", @@ -141,14 +141,14 @@ func TestExtract(t *testing.T) { }, }, { - name: "caskroom.null.variation", - path: "testdata/Caskroom/somefolder/2.2", - wantInventory: []*extractor.Inventory{}, + name: "caskroom.null.variation", + path: "testdata/Caskroom/somefolder/2.2", + wantPackages: []*extractor.Package{}, }, { name: "caskroom.other.variation", path: "testdata/Caskroom/android-platform-tools/35.0.2/platform-tools/source.properties", - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "android-platform-tools", Version: "35.0.2", @@ -168,9 +168,9 @@ func TestExtract(t *testing.T) { t.Errorf("Extract(%s) unexpected error (-want +got):\n%s", tt.path, diff) } - want := tt.wantInventory + want := tt.wantPackages - if diff := cmp.Diff(want, got, cmpopts.SortSlices(invLess)); diff != "" { + if diff := cmp.Diff(want, got, cmpopts.SortSlices(pkgLess)); diff != "" { t.Errorf("Extract(%s) (-want +got):\n%s", tt.path, diff) } }) @@ -179,13 +179,13 @@ func TestExtract(t *testing.T) { func TestToPURL(t *testing.T) { tests := []struct { - name string - inventory []*extractor.Inventory - want *purl.PackageURL + name string + pkgs []*extractor.Package + want *purl.PackageURL }{ { name: "cask_firefox", - inventory: []*extractor.Inventory{ + pkgs: []*extractor.Package{ { Name: "firefox", Version: "129.0", @@ -203,10 +203,10 @@ func TestToPURL(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { var e filesystem.Extractor = homebrew.Extractor{} - for _, i := range tt.inventory { - got := e.ToPURL(i) + for _, p := range tt.pkgs { + got := e.ToPURL(p) if diff := cmp.Diff(tt.want, got); diff != "" { - t.Errorf("ToPURL(%v) (-want +got):\n%s", i, diff) + t.Errorf("ToPURL(%v) (-want +got):\n%s", p, diff) } } }) diff --git a/extractor/filesystem/os/kernel/module/module.go b/extractor/filesystem/os/kernel/module/module.go index 4184d2b4..707bd11c 100644 --- a/extractor/filesystem/os/kernel/module/module.go +++ b/extractor/filesystem/os/kernel/module/module.go @@ -130,8 +130,8 @@ func (e Extractor) reportFileRequired(path string, fileSizeBytes int64, result s } // Extract extracts packages from .ko files passed through the scan input. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { - inventory, err := e.extractFromInput(ctx, input) +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { + pkgs, err := e.extractFromInput(ctx, input) if e.stats != nil { var fileSizeBytes int64 @@ -144,11 +144,11 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] FileSizeBytes: fileSizeBytes, }) } - return inventory, err + return pkgs, err } -func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { - pkgs := []*extractor.Inventory{} +func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { + packages := []*extractor.Package{} m, err := osrelease.GetOSRelease(input.FS) if err != nil { @@ -162,7 +162,7 @@ func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanI buf := bytes.NewBuffer([]byte{}) _, err := io.Copy(buf, input.Reader) if err != nil { - return []*extractor.Inventory{}, err + return []*extractor.Package{}, err } readerAt = bytes.NewReader(buf.Bytes()) } @@ -217,21 +217,21 @@ func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanI metadata.OSVersionCodename = m["VERSION_CODENAME"] metadata.OSVersionID = m["VERSION_ID"] - i := &extractor.Inventory{ + p := &extractor.Package{ Name: metadata.PackageName, Version: metadata.PackageVersion, Metadata: &metadata, Locations: []string{input.Path}, } - pkgs = append(pkgs, i) + packages = append(packages, p) - return pkgs, nil + return packages, nil } // Ecosystem returns the OSV Ecosystem of the software extracted by this extractor. -func (Extractor) Ecosystem(i *extractor.Inventory) string { - m := i.Metadata.(*Metadata) +func (Extractor) Ecosystem(p *extractor.Package) string { + m := p.Metadata.(*Metadata) osID := cases.Title(language.English).String(toNamespace(m)) if m.OSVersionID == "" { return osID @@ -247,9 +247,9 @@ func toNamespace(m *Metadata) string { return "linux" } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { - m := i.Metadata.(*Metadata) +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { + m := p.Metadata.(*Metadata) q := map[string]string{} distro := toDistro(m) if distro != "" { @@ -260,7 +260,7 @@ func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { Type: purl.TypeKernelModule, Name: m.PackageName, Namespace: toNamespace(m), - Version: i.Version, + Version: p.Version, Qualifiers: purl.QualifiersFromMap(q), } } diff --git a/extractor/filesystem/os/kernel/module/module_test.go b/extractor/filesystem/os/kernel/module/module_test.go index 3b9b9fba..f3f203e3 100644 --- a/extractor/filesystem/os/kernel/module/module_test.go +++ b/extractor/filesystem/os/kernel/module/module_test.go @@ -173,7 +173,7 @@ func TestExtract(t *testing.T) { path string osrelease string cfg module.Config - wantInventory []*extractor.Inventory + wantPackages []*extractor.Package wantErr error wantResultMetric stats.FileExtractedResult }{ @@ -181,7 +181,7 @@ func TestExtract(t *testing.T) { name: "valid *.ko file", path: "testdata/valid", osrelease: UbuntuJammy, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "intel_oaktrail", Version: "0.4ac1", @@ -204,7 +204,7 @@ func TestExtract(t *testing.T) { name: "valid *.ko file without version, deps, author", path: "testdata/valid_no_vers_deps_auth", osrelease: UbuntuJammy, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "intel_mrfld_pwrbtn", Metadata: &module.Metadata{ @@ -224,7 +224,7 @@ func TestExtract(t *testing.T) { name: "invalid *.ko file, no .modinfo section", path: "testdata/invalid", osrelease: UbuntuJammy, - wantInventory: nil, + wantPackages: nil, wantErr: cmpopts.AnyError, wantResultMetric: stats.FileExtractedResultErrorUnknown, }, @@ -232,7 +232,7 @@ func TestExtract(t *testing.T) { name: "no os version", path: "testdata/valid", osrelease: `ID=ubuntu`, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "intel_oaktrail", Version: "0.4ac1", @@ -252,7 +252,7 @@ func TestExtract(t *testing.T) { { name: "missing osrelease", path: "testdata/valid", - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "intel_oaktrail", Version: "0.4ac1", @@ -303,8 +303,8 @@ func TestExtract(t *testing.T) { got, err := e.Extract(context.Background(), input) - if diff := cmp.Diff(tt.wantInventory, got); diff != "" { - t.Errorf("Inventory mismatch (-want +got):\n%s", diff) + if diff := cmp.Diff(tt.wantPackages, got); diff != "" { + t.Errorf("Package mismatch (-want +got):\n%s", diff) } if !cmp.Equal(err, tt.wantErr, cmpopts.EquateErrors()) { @@ -318,7 +318,7 @@ func TestToPURL(t *testing.T) { pkgName := "pkgName" pkgVersion := "pkgVersion" pkgVermagic := "pkgVermagic" - pkgSourceVersionIdentifier := "pkgSourceVersionIdentifier" + packageSourceVersionIdentifier := "packageSourceVersionIdentifier" pkgAuthor := "pkgAuthor" e := module.Extractor{} @@ -333,7 +333,7 @@ func TestToPURL(t *testing.T) { PackageName: pkgName, PackageVersion: pkgVersion, PackageVermagic: pkgVermagic, - PackageSourceVersionIdentifier: pkgSourceVersionIdentifier, + PackageSourceVersionIdentifier: packageSourceVersionIdentifier, PackageAuthor: pkgAuthor, OSID: "ubuntu", OSVersionCodename: "jammy", @@ -355,7 +355,7 @@ func TestToPURL(t *testing.T) { PackageName: pkgName, PackageVersion: pkgVersion, PackageVermagic: pkgVermagic, - PackageSourceVersionIdentifier: pkgSourceVersionIdentifier, + PackageSourceVersionIdentifier: packageSourceVersionIdentifier, PackageAuthor: pkgAuthor, OSID: "ubuntu", OSVersionID: "22.04", @@ -376,7 +376,7 @@ func TestToPURL(t *testing.T) { PackageName: pkgName, PackageVersion: pkgVersion, PackageVermagic: pkgVermagic, - PackageSourceVersionIdentifier: pkgSourceVersionIdentifier, + PackageSourceVersionIdentifier: packageSourceVersionIdentifier, PackageAuthor: pkgAuthor, OSVersionID: "22.04", }, @@ -393,15 +393,15 @@ func TestToPURL(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - i := &extractor.Inventory{ + p := &extractor.Package{ Name: pkgName, Version: pkgVersion, Metadata: tt.metadata, Locations: []string{"location"}, } - got := e.ToPURL(i) + got := e.ToPURL(p) if diff := cmp.Diff(tt.want, got); diff != "" { - t.Errorf("ToPURL(%v) (-want +got):\n%s", i, diff) + t.Errorf("ToPURL(%v) (-want +got):\n%s", p, diff) } }) } @@ -437,12 +437,12 @@ func TestEcosystem(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - i := &extractor.Inventory{ + p := &extractor.Package{ Metadata: tt.metadata, } - got := e.Ecosystem(i) + got := e.Ecosystem(p) if diff := cmp.Diff(tt.want, got); diff != "" { - t.Errorf("Ecosystem(%v) (-want +got):\n%s", i, diff) + t.Errorf("Ecosystem(%v) (-want +got):\n%s", p, diff) } }) } diff --git a/extractor/filesystem/os/kernel/vmlinuz/vmlinuz.go b/extractor/filesystem/os/kernel/vmlinuz/vmlinuz.go index d576c43b..6124dc83 100644 --- a/extractor/filesystem/os/kernel/vmlinuz/vmlinuz.go +++ b/extractor/filesystem/os/kernel/vmlinuz/vmlinuz.go @@ -133,8 +133,8 @@ func (e Extractor) reportFileRequired(path string, fileSizeBytes int64, result s } // Extract extracts information from vmlinuz files passed through the scan input. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { - inventory, err := e.extractFromInput(ctx, input) +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { + pkgs, err := e.extractFromInput(ctx, input) if e.stats != nil { var fileSizeBytes int64 @@ -147,11 +147,11 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] FileSizeBytes: fileSizeBytes, }) } - return inventory, err + return pkgs, err } -func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { - pkgs := []*extractor.Inventory{} +func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { + packages := []*extractor.Package{} m, err := osrelease.GetOSRelease(input.FS) if err != nil { @@ -178,16 +178,16 @@ func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanI metadata.OSVersionCodename = m["VERSION_CODENAME"] metadata.OSVersionID = m["VERSION_ID"] - i := &extractor.Inventory{ + p := &extractor.Package{ Name: metadata.Name, Version: metadata.Version, Metadata: &metadata, Locations: []string{input.Path}, } - pkgs = append(pkgs, i) + packages = append(packages, p) - return pkgs, nil + return packages, nil } func parseVmlinuzMetadata(magicType []string) Metadata { @@ -251,8 +251,8 @@ func parseVmlinuzMetadata(magicType []string) Metadata { } // Ecosystem returns the OSV Ecosystem of the software extracted by this extractor. -func (Extractor) Ecosystem(i *extractor.Inventory) string { - m := i.Metadata.(*Metadata) +func (Extractor) Ecosystem(p *extractor.Package) string { + m := p.Metadata.(*Metadata) osID := cases.Title(language.English).String(toNamespace(m)) if m.OSVersionID == "" { return osID @@ -268,9 +268,9 @@ func toNamespace(m *Metadata) string { return "linux" } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { - m := i.Metadata.(*Metadata) +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { + m := p.Metadata.(*Metadata) q := map[string]string{} distro := toDistro(m) if distro != "" { @@ -281,7 +281,7 @@ func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { Type: purl.TypeKernelModule, Name: m.Name, Namespace: toNamespace(m), - Version: i.Version, + Version: p.Version, Qualifiers: purl.QualifiersFromMap(q), } } diff --git a/extractor/filesystem/os/kernel/vmlinuz/vmlinuz_test.go b/extractor/filesystem/os/kernel/vmlinuz/vmlinuz_test.go index 5998b41a..1766f6f7 100644 --- a/extractor/filesystem/os/kernel/vmlinuz/vmlinuz_test.go +++ b/extractor/filesystem/os/kernel/vmlinuz/vmlinuz_test.go @@ -198,7 +198,7 @@ func TestExtract(t *testing.T) { path string osrelease string cfg vmlinuz.Config - wantInventory []*extractor.Inventory + wantPackages []*extractor.Package wantErr error wantResultMetric stats.FileExtractedResult }{ @@ -206,7 +206,7 @@ func TestExtract(t *testing.T) { name: "valid vmlinuz file", path: "testdata/valid", osrelease: UbuntuJammy, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "Linux Kernel", Version: "6.8.0-49-generic", @@ -228,10 +228,10 @@ func TestExtract(t *testing.T) { wantResultMetric: stats.FileExtractedResultSuccess, }, { - name: "invalid vmlinuz file", - path: "testdata/invalid", - osrelease: UbuntuJammy, - wantInventory: nil, + name: "invalid vmlinuz file", + path: "testdata/invalid", + osrelease: UbuntuJammy, + wantPackages: nil, }, } @@ -268,8 +268,8 @@ func TestExtract(t *testing.T) { got, err := e.Extract(context.Background(), input) - if diff := cmp.Diff(tt.wantInventory, got); diff != "" { - t.Errorf("Inventory mismatch (-want +got):\n%s", diff) + if diff := cmp.Diff(tt.wantPackages, got); diff != "" { + t.Errorf("Package mismatch (-want +got):\n%s", diff) } }) } @@ -370,15 +370,15 @@ func TestToPURL(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - i := &extractor.Inventory{ + p := &extractor.Package{ Name: name, Version: version, Metadata: tt.metadata, Locations: []string{"location"}, } - got := e.ToPURL(i) + got := e.ToPURL(p) if diff := cmp.Diff(tt.want, got); diff != "" { - t.Errorf("ToPURL(%v) (-want +got):\n%s", i, diff) + t.Errorf("ToPURL(%v) (-want +got):\n%s", p, diff) } }) } @@ -414,12 +414,12 @@ func TestEcosystem(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - i := &extractor.Inventory{ + p := &extractor.Package{ Metadata: tt.metadata, } - got := e.Ecosystem(i) + got := e.Ecosystem(p) if diff := cmp.Diff(tt.want, got); diff != "" { - t.Errorf("Ecosystem(%v) (-want +got):\n%s", i, diff) + t.Errorf("Ecosystem(%v) (-want +got):\n%s", p, diff) } }) } diff --git a/extractor/filesystem/os/macapps/macapps.go b/extractor/filesystem/os/macapps/macapps.go index 3d5f24ce..5c4f6a22 100644 --- a/extractor/filesystem/os/macapps/macapps.go +++ b/extractor/filesystem/os/macapps/macapps.go @@ -132,8 +132,8 @@ func (e Extractor) reportFileRequired(path string, fileSizeBytes int64, result s } // Extract extracts packages from Info.plist files passed through the scan input. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { - i, err := e.extractFromInput(ctx, input) +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { + p, err := e.extractFromInput(ctx, input) if e.stats != nil { var fileSizeBytes int64 if input.Info != nil { @@ -148,13 +148,13 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] if err != nil { return nil, fmt.Errorf("Mac OS Application.extract(%s): %w", input.Path, err) } - if i == nil { - return []*extractor.Inventory{}, nil + if p == nil { + return []*extractor.Package{}, nil } - return []*extractor.Inventory{i}, nil + return []*extractor.Package{p}, nil } -func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanInput) (*extractor.Inventory, error) { +func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanInput) (*extractor.Package, error) { // Read the first 8 bytes to check for binary plist header header := make([]byte, 8) _, err := io.ReadFull(input.Reader, header) @@ -187,27 +187,27 @@ func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanI } } - i := &extractor.Inventory{ + p := &extractor.Package{ Name: metadata.CFBundleName, Version: metadata.CFBundleShortVersionString, Metadata: &metadata, Locations: []string{input.Path}, } - return i, nil + return p, nil } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { return &purl.PackageURL{ Type: purl.TypeMacApps, - Name: i.Name, - Version: i.Version, + Name: p.Name, + Version: p.Version, } } -// ToCPEs is not applicable as this extractor does not infer CPEs from the Inventory. -func (e Extractor) ToCPEs(i *extractor.Inventory) []string { return nil } +// ToCPEs is not applicable as this extractor does not infer CPEs from the Package. +func (e Extractor) ToCPEs(p *extractor.Package) []string { return nil } // Ecosystem returns no Ecosystem since the ecosystem is not known by OSV yet. -func (e Extractor) Ecosystem(i *extractor.Inventory) string { return "" } +func (e Extractor) Ecosystem(p *extractor.Package) string { return "" } diff --git a/extractor/filesystem/os/macapps/macapps_test.go b/extractor/filesystem/os/macapps/macapps_test.go index 3b5cb9ef..14da778f 100644 --- a/extractor/filesystem/os/macapps/macapps_test.go +++ b/extractor/filesystem/os/macapps/macapps_test.go @@ -131,15 +131,15 @@ func TestExtract(t *testing.T) { tests := []struct { name string path string - wantInventory []*extractor.Inventory + wantPackages []*extractor.Package wantErr error wantResultMetric stats.FileExtractedResult }{ { name: "Valid_XML_Info.plist_data ", path: "testdata/ValidXML.plist", - wantInventory: []*extractor.Inventory{ - &extractor.Inventory{ + wantPackages: []*extractor.Package{ + &extractor.Package{ Name: "Chrome", Version: "130.0.6723.69", Locations: []string{"testdata/ValidXML.plist"}, @@ -162,8 +162,8 @@ func TestExtract(t *testing.T) { { name: "Valid_Binary_Info.plist_data ", path: "testdata/BinaryApp.plist", - wantInventory: []*extractor.Inventory{ - &extractor.Inventory{ + wantPackages: []*extractor.Package{ + &extractor.Package{ Name: "gMacInformation", Version: "202410231131", Locations: []string{"testdata/BinaryApp.plist"}, @@ -198,8 +198,8 @@ func TestExtract(t *testing.T) { { name: "Missing_Info.plist_data ", path: "testdata/MissingData.plist", - wantInventory: []*extractor.Inventory{ - &extractor.Inventory{ + wantPackages: []*extractor.Package{ + &extractor.Package{ Name: "Chrome", Version: "", Locations: []string{"testdata/MissingData.plist"}, @@ -267,7 +267,7 @@ func TestExtract(t *testing.T) { ignoreOrder := cmpopts.SortSlices(func(a, b any) bool { return fmt.Sprintf("%+v", a) < fmt.Sprintf("%+v", b) }) - if diff := cmp.Diff(tt.wantInventory, got, ignoreOrder); diff != "" { + if diff := cmp.Diff(tt.wantPackages, got, ignoreOrder); diff != "" { t.Errorf("Extract(%s) (-want +got):\n%s", tt.path, diff) } diff --git a/extractor/filesystem/os/nix/nix.go b/extractor/filesystem/os/nix/nix.go index c5dce61e..39de9284 100644 --- a/extractor/filesystem/os/nix/nix.go +++ b/extractor/filesystem/os/nix/nix.go @@ -94,7 +94,7 @@ var packageStoreUnstableRegex = regexp.MustCompile(`^([a-zA-Z0-9]{32})-([a-zA-Z0 // Extract extracts packages from the filenames of the directories in the nix // store path. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { // Check for cancellation or timeout. if err := ctx.Err(); err != nil { return nil, fmt.Errorf("%s halted at %q because of context error: %v", e.Name(), input.Path, err) @@ -105,13 +105,13 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] log.Errorf("osrelease.GetOSRelease(): %v", err) } - pkg := strings.Split(input.Path, "/")[2] + pkgs := strings.Split(input.Path, "/")[2] var matches []string - if strings.Contains(pkg, "unstable") { - matches = packageStoreUnstableRegex.FindStringSubmatch(pkg) + if strings.Contains(pkgs, "unstable") { + matches = packageStoreUnstableRegex.FindStringSubmatch(pkgs) } else { - matches = packageStoreRegex.FindStringSubmatch(pkg) + matches = packageStoreRegex.FindStringSubmatch(pkgs) } if len(matches) == 0 { @@ -126,7 +126,7 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] return nil, nil } - i := &extractor.Inventory{ + p := &extractor.Package{ Name: pkgName, Version: pkgVersion, Metadata: &Metadata{ @@ -142,15 +142,15 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] if len(matches) > 4 { pkgOutput := matches[4] - i.Metadata.(*Metadata).PackageOutput = pkgOutput + p.Metadata.(*Metadata).PackageOutput = pkgOutput } - return []*extractor.Inventory{i}, nil + return []*extractor.Package{p}, nil } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { - m := i.Metadata.(*Metadata) +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { + m := p.Metadata.(*Metadata) q := map[string]string{} distro := toDistro(m) @@ -160,14 +160,14 @@ func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { return &purl.PackageURL{ Type: purl.TypeNix, - Name: i.Name, - Version: i.Version, + Name: p.Name, + Version: p.Version, Qualifiers: purl.QualifiersFromMap(q), } } // Ecosystem returns no Ecosystem since the ecosystem is not known by OSV yet. -func (Extractor) Ecosystem(i *extractor.Inventory) string { return "" } +func (Extractor) Ecosystem(p *extractor.Package) string { return "" } func toDistro(m *Metadata) string { if m.OSVersionCodename != "" { diff --git a/extractor/filesystem/os/nix/nix_test.go b/extractor/filesystem/os/nix/nix_test.go index a5bbd3b0..c3eca4f8 100644 --- a/extractor/filesystem/os/nix/nix_test.go +++ b/extractor/filesystem/os/nix/nix_test.go @@ -87,7 +87,7 @@ func TestFileRequired(t *testing.T) { func TestExtract(t *testing.T) { const NixVicuna = `ANSI_COLOR="1;34" - BUG_REPORT_URL="https://github.com/NixOS/nixpkgs/issues" + BUG_REPORT_URL="https://github.com/NixOS/nixpackages/issues" BUILD_ID="24.11.710315.b681065d0919" CPE_NAME="cpe:/o:nixos:nixos:24.11" DEFAULT_HOSTNAME=nixos @@ -114,7 +114,7 @@ func TestExtract(t *testing.T) { name string path string osrelease string - wantInventory []*extractor.Inventory + wantPackages []*extractor.Package wantError error wantResultMetric stats.FileExtractedResult }{ @@ -122,7 +122,7 @@ func TestExtract(t *testing.T) { name: "valid", path: "nix/store/xakcaxsqdzjszym0vji2r8n0wdy2inqc-perl5.38.2-FCGI-ProcManager-0.28/foo", osrelease: NixVicuna, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "perl5.38.2-FCGI-ProcManager", Version: "0.28", @@ -144,7 +144,7 @@ func TestExtract(t *testing.T) { name: "valid", path: "nix/store/q5dhwzcn82by5ndc7g0q83wsnn13qkqw-webdav-server-rs-unstable-2021-08-16/foo", osrelease: NixVicuna, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "webdav-server-rs", Version: "unstable-2021-08-16", @@ -163,34 +163,34 @@ func TestExtract(t *testing.T) { wantResultMetric: stats.FileExtractedResultSuccess, }, { - name: "invalid package hash", - path: "nix/store/foo-webdav-server-rs-unstable-2021-08-16/foo", - osrelease: NixVicuna, - wantInventory: nil, + name: "invalid package hash", + path: "nix/store/foo-webdav-server-rs-unstable-2021-08-16/foo", + osrelease: NixVicuna, + wantPackages: nil, }, { - name: "no package name", - path: "nix/store/xakcaxsqdzjszym0vji2r8n0wdy2inqc-0.28/foo", - osrelease: NixVicuna, - wantInventory: nil, + name: "no package name", + path: "nix/store/xakcaxsqdzjszym0vji2r8n0wdy2inqc-0.28/foo", + osrelease: NixVicuna, + wantPackages: nil, }, { - name: "no package version", - path: "nix/store/xakcaxsqdzjszym0vji2r8n0wdy2inqc-perl5.38.2-FCGI-ProcManager/foo", - osrelease: NixVicuna, - wantInventory: nil, + name: "no package version", + path: "nix/store/xakcaxsqdzjszym0vji2r8n0wdy2inqc-perl5.38.2-FCGI-ProcManager/foo", + osrelease: NixVicuna, + wantPackages: nil, }, { - name: "invalid", - path: "nix/store/xzlmnp0lblcbscy36nlgif3js4mc68gm-base-system/etc/group", - osrelease: NixVicuna, - wantInventory: nil, + name: "invalid", + path: "nix/store/xzlmnp0lblcbscy36nlgif3js4mc68gm-base-system/etc/group", + osrelease: NixVicuna, + wantPackages: nil, }, { - name: "invalid", - path: "nix/store/a-b-c-d-e/foo", - osrelease: NixVicuna, - wantInventory: nil, + name: "invalid", + path: "nix/store/a-b-c-d-e/foo", + osrelease: NixVicuna, + wantPackages: nil, }, } @@ -215,8 +215,8 @@ func TestExtract(t *testing.T) { t.Errorf("err = %v", err) } - if diff := cmp.Diff(tt.wantInventory, got); diff != "" { - t.Errorf("Inventory mismatch (-want +got):\n%s", diff) + if diff := cmp.Diff(tt.wantPackages, got); diff != "" { + t.Errorf("Package mismatch (-want +got):\n%s", diff) } }) } @@ -295,15 +295,15 @@ func TestToPURL(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - i := &extractor.Inventory{ + p := &extractor.Package{ Name: pkgName, Version: pkgVersion, Metadata: tt.metadata, Locations: []string{"location"}, } - got := e.ToPURL(i) + got := e.ToPURL(p) if diff := cmp.Diff(tt.want, got); diff != "" { - t.Errorf("ToPURL(%v) (-want +got):\n%s", i, diff) + t.Errorf("ToPURL(%v) (-want +got):\n%s", p, diff) } }) } diff --git a/extractor/filesystem/os/pacman/pacman.go b/extractor/filesystem/os/pacman/pacman.go index aa993c3e..a6bb0fe0 100644 --- a/extractor/filesystem/os/pacman/pacman.go +++ b/extractor/filesystem/os/pacman/pacman.go @@ -131,8 +131,8 @@ func (e Extractor) reportFileRequired(path string, fileSizeBytes int64, result s } // Extract extracts packages from "desc" files passed through the scan input. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { - inventory, err := e.extractFromInput(ctx, input) +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { + pkgs, err := e.extractFromInput(ctx, input) if e.stats != nil { var fileSizeBytes int64 @@ -145,10 +145,10 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] FileSizeBytes: fileSizeBytes, }) } - return inventory, err + return pkgs, err } -func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { m, err := osrelease.GetOSRelease(input.FS) if err != nil { log.Errorf("osrelease.ParseOsRelease(): %v", err) @@ -156,12 +156,12 @@ func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanI s := bufio.NewScanner(input.Reader) var pkgName, pkgVersion, pkgDependencies string - pkgs := []*extractor.Inventory{} + packages := []*extractor.Package{} for s.Scan() { // Return if canceled or exceeding deadline. if err := ctx.Err(); err != nil { - return pkgs, fmt.Errorf("%s halted at %q because of context error: %v", e.Name(), input.Path, err) + return packages, fmt.Errorf("%s halted at %q because of context error: %v", e.Name(), input.Path, err) } line := s.Text() @@ -184,12 +184,12 @@ func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanI log.Warnf("Reached EOF for desc file in %v", input.Path) break } - return pkgs, fmt.Errorf("%s halted at %q: %v", e.Name(), input.Path, err) + return packages, fmt.Errorf("%s halted at %q: %v", e.Name(), input.Path, err) } } if pkgName != "" && pkgVersion != "" { - i := &extractor.Inventory{ + p := &extractor.Package{ Name: pkgName, Version: pkgVersion, Metadata: &Metadata{ @@ -202,13 +202,13 @@ func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanI } if len(pkgDependencies) != 0 { - i.Metadata.(*Metadata).PackageDependencies = pkgDependencies + p.Metadata.(*Metadata).PackageDependencies = pkgDependencies } - pkgs = append(pkgs, i) + packages = append(packages, p) } - return pkgs, nil + return packages, nil } func extractValue(scanner *bufio.Scanner) (string, error) { @@ -250,8 +250,8 @@ func extractValues(scanner *bufio.Scanner) (string, error) { } // Ecosystem returns the OSV Ecosystem of the software extracted by this extractor. -func (Extractor) Ecosystem(i *extractor.Inventory) string { - m := i.Metadata.(*Metadata) +func (Extractor) Ecosystem(p *extractor.Package) string { + m := p.Metadata.(*Metadata) osID := cases.Title(language.English).String(toNamespace(m)) if m.OSVersionID == "" { return osID @@ -267,9 +267,9 @@ func toNamespace(m *Metadata) string { return "linux" } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { - m := i.Metadata.(*Metadata) +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { + m := p.Metadata.(*Metadata) q := map[string]string{} distro := toDistro(m) if distro != "" { @@ -283,7 +283,7 @@ func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { Type: purl.TypePacman, Name: m.PackageName, Namespace: toNamespace(m), - Version: i.Version, + Version: p.Version, Qualifiers: purl.QualifiersFromMap(q), } } diff --git a/extractor/filesystem/os/pacman/pacman_test.go b/extractor/filesystem/os/pacman/pacman_test.go index 8a33e589..1cfcd310 100644 --- a/extractor/filesystem/os/pacman/pacman_test.go +++ b/extractor/filesystem/os/pacman/pacman_test.go @@ -183,7 +183,7 @@ func TestExtract(t *testing.T) { path string osrelease string cfg pacman.Config - wantInventory []*extractor.Inventory + wantPackages []*extractor.Package wantErr error wantResultMetric stats.FileExtractedResult }{ @@ -191,7 +191,7 @@ func TestExtract(t *testing.T) { name: "valid desc file", path: "testdata/valid", osrelease: ArchRolling, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "gawk", Version: "5.3.1-1", @@ -211,7 +211,7 @@ func TestExtract(t *testing.T) { name: "valid desc file one dependency", path: "testdata/valid_one_dep", osrelease: ArchRolling, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "filesystem", Version: "2024.11.21-1", @@ -231,7 +231,7 @@ func TestExtract(t *testing.T) { name: "valid desc file no dependencies", path: "testdata/valid_no_dep", osrelease: ArchRolling, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "libxml2", Version: "2.13.5-1", @@ -250,7 +250,7 @@ func TestExtract(t *testing.T) { name: "no os version", path: "testdata/valid", osrelease: `ID=arch`, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "gawk", Version: "5.3.1-1", @@ -268,7 +268,7 @@ func TestExtract(t *testing.T) { { name: "missing osrelease", path: "testdata/valid", - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "gawk", Version: "5.3.1-1", @@ -283,16 +283,16 @@ func TestExtract(t *testing.T) { wantResultMetric: stats.FileExtractedResultSuccess, }, { - name: "invalid value eof", - path: "testdata/invalid_value_eof", - osrelease: ArchRolling, - wantInventory: []*extractor.Inventory{}, + name: "invalid value eof", + path: "testdata/invalid_value_eof", + osrelease: ArchRolling, + wantPackages: []*extractor.Package{}, }, { name: "eof after dependencies", path: "testdata/eof_after_dependencies", osrelease: ArchRolling, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "gawk", Version: "5.3.1-1", @@ -343,8 +343,8 @@ func TestExtract(t *testing.T) { got, err := e.Extract(context.Background(), input) - if diff := cmp.Diff(tt.wantInventory, got); diff != "" { - t.Errorf("Inventory mismatch (-want +got):\n%s", diff) + if diff := cmp.Diff(tt.wantPackages, got); diff != "" { + t.Errorf("Package mismatch (-want +got):\n%s", diff) } }) } @@ -423,15 +423,15 @@ func TestToPURL(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - i := &extractor.Inventory{ + p := &extractor.Package{ Name: pkgName, Version: pkgVersion, Metadata: tt.metadata, Locations: []string{"location"}, } - got := e.ToPURL(i) + got := e.ToPURL(p) if diff := cmp.Diff(tt.want, got); diff != "" { - t.Errorf("ToPURL(%v) (-want +got):\n%s", i, diff) + t.Errorf("ToPURL(%v) (-want +got):\n%s", p, diff) } }) } @@ -467,12 +467,12 @@ func TestEcosystem(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - i := &extractor.Inventory{ + p := &extractor.Package{ Metadata: tt.metadata, } - got := e.Ecosystem(i) + got := e.Ecosystem(p) if diff := cmp.Diff(tt.want, got); diff != "" { - t.Errorf("Ecosystem(%v) (-want +got):\n%s", i, diff) + t.Errorf("Ecosystem(%v) (-want +got):\n%s", p, diff) } }) } diff --git a/extractor/filesystem/os/portage/portage.go b/extractor/filesystem/os/portage/portage.go index 62f732be..c68d57ea 100644 --- a/extractor/filesystem/os/portage/portage.go +++ b/extractor/filesystem/os/portage/portage.go @@ -139,10 +139,10 @@ func (e Extractor) reportFileRequired(path string, fileSizeBytes int64, result s } // Extract extracts packages from portage database files passed through the scan input. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { - inventory, err := e.extractFromInput(ctx, input) +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { + pkgs, err := e.extractFromInput(ctx, input) if e.stats == nil { - return inventory, err + return pkgs, err } var fileSizeBytes int64 if input.Info != nil { @@ -153,10 +153,10 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] Result: filesystem.ExtractorErrorToFileExtractedResult(err), FileSizeBytes: fileSizeBytes, }) - return inventory, err + return pkgs, err } -func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { osRelease, err := osrelease.GetOSRelease(input.FS) if err != nil { log.Errorf("osrelease.GetOSRelease(): %v", err) @@ -180,7 +180,7 @@ func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanI return nil, fmt.Errorf("no package name or version found in PF file: %s", pf) } - i := &extractor.Inventory{ + p := &extractor.Package{ Name: pkgName, Version: pkgVersion, Metadata: &Metadata{ @@ -192,7 +192,7 @@ func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanI Locations: []string{input.Path}, } - return []*extractor.Inventory{i}, nil + return []*extractor.Package{p}, nil } func splitPackageAndVersion(path string) (string, string) { @@ -232,9 +232,9 @@ func toDistro(m *Metadata) string { return "" } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { - m := i.Metadata.(*Metadata) +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { + m := p.Metadata.(*Metadata) q := map[string]string{} distro := toDistro(m) if distro != "" { @@ -250,8 +250,8 @@ func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { } // Ecosystem returns the OSV Ecosystem of the software extracted by this extractor. -func (Extractor) Ecosystem(i *extractor.Inventory) string { - m := i.Metadata.(*Metadata) +func (Extractor) Ecosystem(p *extractor.Package) string { + m := p.Metadata.(*Metadata) osID := cases.Title(language.English).String(toNamespace(m)) if m.OSVersionID == "" { return osID diff --git a/extractor/filesystem/os/portage/portage_test.go b/extractor/filesystem/os/portage/portage_test.go index 5c31f35c..3d54e33c 100644 --- a/extractor/filesystem/os/portage/portage_test.go +++ b/extractor/filesystem/os/portage/portage_test.go @@ -169,7 +169,7 @@ func TestExtract(t *testing.T) { path string osrelease string cfg portage.Config - wantInventory []*extractor.Inventory + wantPackages []*extractor.Package wantErr error wantResultMetric stats.FileExtractedResult }{ @@ -177,7 +177,7 @@ func TestExtract(t *testing.T) { name: "valid PF file", path: "testdata/valid", osrelease: Gentoo, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "Getopt-Long", Version: "2.580.0", @@ -196,7 +196,7 @@ func TestExtract(t *testing.T) { name: "not valid PF file", path: "testdata/invalid", osrelease: Gentoo, - wantInventory: nil, + wantPackages: nil, wantErr: cmpopts.AnyError, wantResultMetric: stats.FileExtractedResultErrorUnknown, }, @@ -204,15 +204,15 @@ func TestExtract(t *testing.T) { name: "no version PF file", path: "testdata/noversion", osrelease: Gentoo, - wantInventory: nil, + wantPackages: nil, wantErr: cmpopts.AnyError, wantResultMetric: stats.FileExtractedResultErrorUnknown, }, { - name: "no pkg name PF file", + name: "no package name PF file", path: "testdata/nopackage", osrelease: Gentoo, - wantInventory: nil, + wantPackages: nil, wantErr: cmpopts.AnyError, wantResultMetric: stats.FileExtractedResultErrorUnknown, }, @@ -220,7 +220,7 @@ func TestExtract(t *testing.T) { name: "empty PF file", path: "testdata/empty", osrelease: Gentoo, - wantInventory: nil, + wantPackages: nil, wantErr: cmpopts.AnyError, wantResultMetric: stats.FileExtractedResultErrorUnknown, }, @@ -259,8 +259,8 @@ func TestExtract(t *testing.T) { got, err := e.Extract(context.Background(), input) - if diff := cmp.Diff(tt.wantInventory, got); diff != "" { - t.Errorf("Inventory mismatch (-want +got):\n%s", diff) + if diff := cmp.Diff(tt.wantPackages, got); diff != "" { + t.Errorf("Package mismatch (-want +got):\n%s", diff) } if !cmp.Equal(err, tt.wantErr, cmpopts.EquateErrors()) { t.Fatalf("Extract(%+v) error: got %v, want %v\n", tt.path, err, tt.wantErr) @@ -335,15 +335,15 @@ func TestToPURL(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - i := &extractor.Inventory{ + p := &extractor.Package{ Name: pkgName, Version: pkgVersion, Metadata: tt.metadata, Locations: []string{"location"}, } - got := e.ToPURL(i) + got := e.ToPURL(p) if diff := cmp.Diff(tt.want, got); diff != "" { - t.Errorf("ToPURL(%v) (-want +got):\n%s", i, diff) + t.Errorf("ToPURL(%v) (-want +got):\n%s", p, diff) } }) } @@ -379,12 +379,12 @@ func TestEcosystem(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - i := &extractor.Inventory{ + p := &extractor.Package{ Metadata: tt.metadata, } - got := e.Ecosystem(i) + got := e.Ecosystem(p) if diff := cmp.Diff(tt.want, got); diff != "" { - t.Errorf("Ecosystem(%v) (-want +got):\n%s", i, diff) + t.Errorf("Ecosystem(%v) (-want +got):\n%s", p, diff) } }) } diff --git a/extractor/filesystem/os/rpm/rpm_dummy.go b/extractor/filesystem/os/rpm/rpm_dummy.go index e058724e..4da9e719 100644 --- a/extractor/filesystem/os/rpm/rpm_dummy.go +++ b/extractor/filesystem/os/rpm/rpm_dummy.go @@ -72,12 +72,12 @@ func (e Extractor) FileRequired(_ filesystem.FileAPI) bool { } // Extract extracts packages from rpm status files passed through the scan input. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { return nil, fmt.Errorf("not supported") } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { return nil } +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { return nil } // Ecosystem is not defined. -func (Extractor) Ecosystem(i *extractor.Inventory) string { return "" } +func (Extractor) Ecosystem(p *extractor.Package) string { return "" } diff --git a/extractor/filesystem/os/rpm/rpm_linux.go b/extractor/filesystem/os/rpm/rpm_linux.go index 1db06a06..8fd3c7bd 100644 --- a/extractor/filesystem/os/rpm/rpm_linux.go +++ b/extractor/filesystem/os/rpm/rpm_linux.go @@ -147,8 +147,8 @@ func (e Extractor) reportFileRequired(path string, fileSizeBytes int64, result s } // Extract extracts packages from rpm status files passed through the scan input. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { - inventory, err := e.extractFromInput(ctx, input) +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { + pkgs, err := e.extractFromInput(ctx, input) if e.stats != nil { var fileSizeBytes int64 if input.Info != nil { @@ -160,10 +160,10 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] FileSizeBytes: fileSizeBytes, }) } - return inventory, err + return pkgs, err } -func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { absPath, err := input.GetRealPath() if err != nil { return nil, fmt.Errorf("GetRealPath(%v): %w", input, err) @@ -187,7 +187,7 @@ func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanI log.Errorf("osrelease.ParseOsRelease(): %v", err) } - pkgs := []*extractor.Inventory{} + pkgs := []*extractor.Package{} for _, p := range rpmPkgs { metadata := &Metadata{ PackageName: p.Name, @@ -202,14 +202,12 @@ func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanI License: p.License, } - i := &extractor.Inventory{ + pkgs = append(pkgs, &extractor.Package{ Name: p.Name, Version: fmt.Sprintf("%s-%s", p.Version, p.Release), Locations: []string{input.Path}, Metadata: metadata, - } - - pkgs = append(pkgs, i) + }) } return pkgs, nil @@ -298,9 +296,9 @@ func toDistro(m *Metadata) string { return fmt.Sprintf("%s-%s", id, v) } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { - m := i.Metadata.(*Metadata) +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { + m := p.Metadata.(*Metadata) q := map[string]string{} if m.Epoch > 0 { q[purl.Epoch] = strconv.Itoa(m.Epoch) @@ -318,15 +316,15 @@ func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { return &purl.PackageURL{ Type: purl.TypeRPM, Namespace: toNamespace(m), - Name: i.Name, - Version: i.Version, + Name: p.Name, + Version: p.Version, Qualifiers: purl.QualifiersFromMap(q), } } // Ecosystem returns the OSV Ecosystem of the software extracted by this extractor. -func (Extractor) Ecosystem(i *extractor.Inventory) string { - m := i.Metadata.(*Metadata) +func (Extractor) Ecosystem(p *extractor.Package) string { + m := p.Metadata.(*Metadata) if m.OSID == "rhel" { return "Red Hat" } else if m.OSID == "rocky" { diff --git a/extractor/filesystem/os/rpm/rpm_test.go b/extractor/filesystem/os/rpm/rpm_test.go index 539b15d2..37124ac8 100644 --- a/extractor/filesystem/os/rpm/rpm_test.go +++ b/extractor/filesystem/os/rpm/rpm_test.go @@ -182,7 +182,7 @@ func TestExtract(t *testing.T) { osrelease string timeoutval time.Duration // rpm -qa --qf "%{NAME}@%{VERSION}-%{RELEASE}\n" |sort |head -n 3 - wantInventory []*extractor.Inventory + wantPackages []*extractor.Package // rpm -qa | wc -l wantResults int wantErr error @@ -194,7 +194,7 @@ func TestExtract(t *testing.T) { path: "testdata/Packages.db", osrelease: fedora38, wantResultMetric: stats.FileExtractedResultSuccess, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Locations: []string{"testdata/Packages.db"}, Name: "aaa_base", @@ -252,7 +252,7 @@ func TestExtract(t *testing.T) { path: "testdata/Packages", osrelease: fedora38, wantResultMetric: stats.FileExtractedResultSuccess, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Locations: []string{"testdata/Packages"}, Name: "acl", @@ -307,7 +307,7 @@ func TestExtract(t *testing.T) { { name: "file not found", path: "testdata/foobar", - wantInventory: nil, + wantPackages: nil, wantResults: 0, wantErr: os.ErrNotExist, wantResultMetric: stats.FileExtractedResultErrorUnknown, @@ -315,7 +315,7 @@ func TestExtract(t *testing.T) { { name: "empty", path: "testdata/empty.sqlite", - wantInventory: nil, + wantPackages: nil, wantResults: 0, wantErr: io.EOF, wantResultMetric: stats.FileExtractedResultErrorUnknown, @@ -323,7 +323,7 @@ func TestExtract(t *testing.T) { { name: "invalid", path: "testdata/invalid", - wantInventory: nil, + wantPackages: nil, wantResults: 0, wantErr: io.ErrUnexpectedEOF, wantResultMetric: stats.FileExtractedResultErrorUnknown, @@ -332,7 +332,7 @@ func TestExtract(t *testing.T) { name: "corrupt db times out", path: "testdata/timeout/Packages", timeoutval: 1 * time.Second, - wantInventory: nil, + wantPackages: nil, wantResults: 0, wantErr: cmpopts.AnyError, wantResultMetric: stats.FileExtractedResultErrorUnknown, @@ -343,7 +343,7 @@ func TestExtract(t *testing.T) { path: "testdata/rpmdb.sqlite", osrelease: fedora38, wantResultMetric: stats.FileExtractedResultSuccess, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Locations: []string{"testdata/rpmdb.sqlite"}, Name: "alternatives", @@ -402,7 +402,7 @@ func TestExtract(t *testing.T) { osrelease: `ID=fedora BUILD_ID=asdf`, wantResultMetric: stats.FileExtractedResultSuccess, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Locations: []string{"testdata/rpmdb.sqlite"}, Name: "alternatives", @@ -464,7 +464,7 @@ func TestExtract(t *testing.T) { PRETTY_NAME="Fedora 32 (Container Image)" CPE_NAME="cpe:/o:fedoraproject:fedora:32"`, wantResultMetric: stats.FileExtractedResultSuccess, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Locations: []string{"testdata/Packages"}, Name: "hello", @@ -519,13 +519,13 @@ func TestExtract(t *testing.T) { } // Update location with the temp path. - for _, i := range tt.wantInventory { - i.Locations = []string{filepath.Base(tmpPath)} + for _, p := range tt.wantPackages { + p.Locations = []string{filepath.Base(tmpPath)} } sort.Slice(got, func(i, j int) bool { return got[i].Name < got[j].Name }) gotFirst3 := got[:min(len(got), 3)] - if diff := cmp.Diff(tt.wantInventory, gotFirst3); diff != "" { + if diff := cmp.Diff(tt.wantPackages, gotFirst3); diff != "" { t.Errorf("Extract(%s) (-want +got):\n%s", tmpPath, diff) } @@ -562,7 +562,7 @@ func TestExtract_VirtualFilesystem(t *testing.T) { osrelease string timeoutval time.Duration // rpm -qa --qf "%{NAME}@%{VERSION}-%{RELEASE}\n" |sort |head -n 3 - wantInventory []*extractor.Inventory + wantPackages []*extractor.Package // rpm -qa | wc -l wantResults int wantErr error @@ -572,7 +572,7 @@ func TestExtract_VirtualFilesystem(t *testing.T) { // docker run --rm --entrypoint cat opensuse/leap:15.5 /var/lib/rpm/Packages.db > third_party/scalibr/extractor/filesystem/os/rpm/testdata/Packages.db path: "testdata/Packages.db", osrelease: fedora38, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Locations: []string{"testdata/Packages.db"}, Name: "aaa_base", @@ -629,7 +629,7 @@ func TestExtract_VirtualFilesystem(t *testing.T) { // docker run --rm --entrypoint cat centos:centos7.9.2009 /var/lib/rpm/Packages > third_party/scalibr/extractor/filesystem/os/rpm/testdata/Packages path: "testdata/Packages", osrelease: fedora38, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Locations: []string{"testdata/Packages"}, Name: "acl", @@ -686,7 +686,7 @@ func TestExtract_VirtualFilesystem(t *testing.T) { // docker run --rm --entrypoint cat rockylinux:9.2.20230513 /var/lib/rpm/rpmdb.sqlite > third_party/scalibr/extractor/filesystem/os/rpm/testdata/rpmdb.sqlite path: "testdata/rpmdb.sqlite", osrelease: fedora38, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Locations: []string{"testdata/rpmdb.sqlite"}, Name: "alternatives", @@ -751,7 +751,7 @@ func TestExtract_VirtualFilesystem(t *testing.T) { PRETTY_NAME="Fedora 32 (Container Image)" CPE_NAME="cpe:/o:fedoraproject:fedora:32"`, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Locations: []string{"testdata/Packages_epoch"}, Name: "hello", @@ -771,18 +771,18 @@ func TestExtract_VirtualFilesystem(t *testing.T) { wantResults: 1, }, { - name: "empty", - path: "testdata/empty.sqlite", - wantInventory: nil, - wantResults: 0, - wantErr: io.EOF, + name: "empty", + path: "testdata/empty.sqlite", + wantPackages: nil, + wantResults: 0, + wantErr: io.EOF, }, { - name: "invalid", - path: "testdata/invalid", - wantInventory: nil, - wantResults: 0, - wantErr: io.ErrUnexpectedEOF, + name: "invalid", + path: "testdata/invalid", + wantPackages: nil, + wantResults: 0, + wantErr: io.ErrUnexpectedEOF, }, } @@ -821,7 +821,7 @@ func TestExtract_VirtualFilesystem(t *testing.T) { sort.Slice(got, func(i, j int) bool { return got[i].Name < got[j].Name }) gotFirst3 := got[:min(len(got), 3)] - if diff := cmp.Diff(tt.wantInventory, gotFirst3); diff != "" { + if diff := cmp.Diff(tt.wantPackages, gotFirst3); diff != "" { t.Errorf("Extract(%s) (-want +got):\n%s", tt.path, diff) } @@ -922,15 +922,15 @@ func TestToPURL(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - i := &extractor.Inventory{ + p := &extractor.Package{ Name: pkgname, Version: version, Metadata: tt.metadata, Locations: []string{"location"}, } - got := e.ToPURL(i) + got := e.ToPURL(p) if diff := cmp.Diff(tt.want, got); diff != "" { - t.Errorf("ToPURL(%v) (-want +got):\n%s", i, diff) + t.Errorf("ToPURL(%v) (-want +got):\n%s", p, diff) } }) } @@ -969,12 +969,12 @@ func TestEcosystem(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - i := &extractor.Inventory{ + p := &extractor.Package{ Metadata: tt.metadata, } - got := e.Ecosystem(i) + got := e.Ecosystem(p) if diff := cmp.Diff(tt.want, got); diff != "" { - t.Errorf("Ecosystem(%v) (-want +got):\n%s", i, diff) + t.Errorf("Ecosystem(%v) (-want +got):\n%s", p, diff) } }) } diff --git a/extractor/filesystem/os/snap/snap.go b/extractor/filesystem/os/snap/snap.go index 12dda58e..8c8f221e 100644 --- a/extractor/filesystem/os/snap/snap.go +++ b/extractor/filesystem/os/snap/snap.go @@ -138,8 +138,8 @@ func (e Extractor) reportFileRequired(path string, fileSizeBytes int64, result s } // Extract extracts snap info from snap.yaml file passed through the scan input. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { - inventory, err := e.extractFromInput(ctx, input) +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { + pkgs, err := e.extractFromInput(ctx, input) if e.stats != nil { var fileSizeBytes int64 if input.Info != nil { @@ -151,10 +151,10 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] FileSizeBytes: fileSizeBytes, }) } - return inventory, err + return pkgs, err } -func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { m, err := osrelease.GetOSRelease(input.FS) if err != nil { log.Errorf("osrelease.ParseOsRelease(): %v", err) @@ -174,7 +174,7 @@ func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanI return nil, fmt.Errorf("missing snap version from %q", input.Path) } - inventory := &extractor.Inventory{ + pkg := &extractor.Package{ Name: snap.Name, Version: snap.Version, Metadata: &Metadata{ @@ -189,7 +189,7 @@ func (e Extractor) extractFromInput(ctx context.Context, input *filesystem.ScanI }, Locations: []string{input.Path}, } - return []*extractor.Inventory{inventory}, nil + return []*extractor.Package{pkg}, nil } func toNamespace(m *Metadata) string { @@ -214,9 +214,9 @@ func toDistro(m *Metadata) string { return "" } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { - m := i.Metadata.(*Metadata) +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { + m := p.Metadata.(*Metadata) q := map[string]string{} distro := toDistro(m) if distro != "" { @@ -233,8 +233,8 @@ func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { } // Ecosystem returns the OSV Ecosystem of the software extracted by this extractor. -func (Extractor) Ecosystem(i *extractor.Inventory) string { - m := i.Metadata.(*Metadata) +func (Extractor) Ecosystem(p *extractor.Package) string { + m := p.Metadata.(*Metadata) if m.OSID == "ubuntu" { return "Ubuntu" } diff --git a/extractor/filesystem/os/snap/snap_test.go b/extractor/filesystem/os/snap/snap_test.go index b6c0880b..f3f302bd 100644 --- a/extractor/filesystem/os/snap/snap_test.go +++ b/extractor/filesystem/os/snap/snap_test.go @@ -152,7 +152,7 @@ func TestExtract(t *testing.T) { name string path string osrelease string - wantInventory []*extractor.Inventory + wantPackages []*extractor.Package wantErr error wantResultMetric stats.FileExtractedResult }{ @@ -167,7 +167,7 @@ func TestExtract(t *testing.T) { name: "valid yaml with single arch", path: "testdata/single-arch.yaml", osrelease: DebianBookworm, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "core", Version: "16-2.61.4-20240607", @@ -190,7 +190,7 @@ func TestExtract(t *testing.T) { name: "valid yaml with multiple arch", path: "testdata/multi-arch.yaml", osrelease: DebianBookworm, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "core", Version: "16-2.61.4-20240607", @@ -266,7 +266,7 @@ func TestExtract(t *testing.T) { ignoreOrder := cmpopts.SortSlices(func(a, b any) bool { return fmt.Sprintf("%+v", a) < fmt.Sprintf("%+v", b) }) - if diff := cmp.Diff(tt.wantInventory, got, ignoreOrder); diff != "" { + if diff := cmp.Diff(tt.wantPackages, got, ignoreOrder); diff != "" { t.Errorf("Extract(%s) (-want +got):\n%s", tt.path, diff) } @@ -362,15 +362,15 @@ func TestToPURL(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - i := &extractor.Inventory{ + p := &extractor.Package{ Name: snapName, Version: snapVersion, Metadata: tt.metadata, Locations: []string{"location"}, } - got := e.ToPURL(i) + got := e.ToPURL(p) if diff := cmp.Diff(tt.want, got); diff != "" { - t.Errorf("ToPURL(%v) (-want +got):\n%s", i, diff) + t.Errorf("ToPURL(%v) (-want +got):\n%s", p, diff) } }) } @@ -398,12 +398,12 @@ func TestEcosystem(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - i := &extractor.Inventory{ + p := &extractor.Package{ Metadata: tt.metadata, } - got := e.Ecosystem(i) + got := e.Ecosystem(p) if diff := cmp.Diff(tt.want, got); diff != "" { - t.Errorf("Ecosystem(%v) (-want +got):\n%s", i, diff) + t.Errorf("Ecosystem(%v) (-want +got):\n%s", p, diff) } }) } diff --git a/extractor/filesystem/osv/metadata.go b/extractor/filesystem/osv/metadata.go index 7926abdb..be7fd12f 100644 --- a/extractor/filesystem/osv/metadata.go +++ b/extractor/filesystem/osv/metadata.go @@ -23,7 +23,7 @@ type Metadata struct { CompareAs string } -// DepGroups provides access to the list of dependency groups an inventory item belongs to. +// DepGroups provides access to the list of dependency groups a package item belongs to. // Dependency groups are used by many language package managers as a way to organize // dependencies (e.g. development dependencies will be in the "dev" group) type DepGroups interface { diff --git a/extractor/filesystem/sbom/cdx/cdx.go b/extractor/filesystem/sbom/cdx/cdx.go index 177d4a81..9276e977 100644 --- a/extractor/filesystem/sbom/cdx/cdx.go +++ b/extractor/filesystem/sbom/cdx/cdx.go @@ -69,7 +69,7 @@ func (e Extractor) FileRequired(api filesystem.FileAPI) bool { } // Extract parses the CycloneDX SBOM and returns a list purls from the SBOM. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { var cdxExtractor = findExtractor(input.Path) if cdxExtractor == nil { @@ -81,7 +81,7 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] return nil, err } - return e.convertCdxBomToInventory(&cdxBOM, input.Path) + return e.convertCdxBomToPackage(&cdxBOM, input.Path) } func findExtractor(path string) extractFunc { @@ -109,21 +109,21 @@ func findExtractor(path string) extractFunc { return nil } -func (e Extractor) convertCdxBomToInventory(cdxBom *cyclonedx.BOM, path string) ([]*extractor.Inventory, error) { - results := []*extractor.Inventory{} +func (e Extractor) convertCdxBomToPackage(cdxBom *cyclonedx.BOM, path string) ([]*extractor.Package, error) { + results := []*extractor.Package{} if cdxBom == nil { return results, nil } for _, cdxPkg := range *cdxBom.Components { - inv := &extractor.Inventory{ + pkg := &extractor.Package{ Locations: []string{path}, Metadata: &Metadata{}, } - m := inv.Metadata.(*Metadata) - inv.Name = cdxPkg.Name - inv.Version = cdxPkg.Version + m := pkg.Metadata.(*Metadata) + pkg.Name = cdxPkg.Name + pkg.Version = cdxPkg.Version if cdxPkg.CPE != "" { m.CPEs = append(m.CPEs, cdxPkg.CPE) } @@ -133,20 +133,20 @@ func (e Extractor) convertCdxBomToInventory(cdxBom *cyclonedx.BOM, path string) log.Warnf("Invalid PURL %q for package ref: %q", cdxPkg.PackageURL, cdxPkg.BOMRef) } else { m.PURL = &packageURL - if inv.Name == "" { - inv.Name = packageURL.Name + if pkg.Name == "" { + pkg.Name = packageURL.Name } - if inv.Version == "" { - inv.Version = packageURL.Version + if pkg.Version == "" { + pkg.Version = packageURL.Version } } } - inv.Metadata = m + pkg.Metadata = m if m.PURL == nil && len(m.CPEs) == 0 { log.Warnf("Neither CPE nor PURL found for package: %+v", cdxPkg) continue } - results = append(results, inv) + results = append(results, pkg) } return results, nil @@ -156,14 +156,14 @@ func hasFileExtension(path string, extension string) bool { return strings.HasSuffix(strings.ToLower(path), extension) } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { - return i.Metadata.(*Metadata).PURL +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { + return p.Metadata.(*Metadata).PURL } // Ecosystem returns the OSV Ecosystem of the software extracted by this extractor. -func (Extractor) Ecosystem(i *extractor.Inventory) string { - purl := i.Metadata.(*Metadata).PURL +func (Extractor) Ecosystem(p *extractor.Package) string { + purl := p.Metadata.(*Metadata).PURL if purl == nil { return "" } diff --git a/extractor/filesystem/sbom/cdx/cdx_test.go b/extractor/filesystem/sbom/cdx/cdx_test.go index 6550218a..c2555d5a 100644 --- a/extractor/filesystem/sbom/cdx/cdx_test.go +++ b/extractor/filesystem/sbom/cdx/cdx_test.go @@ -102,15 +102,15 @@ func TestExtract(t *testing.T) { var e filesystem.Extractor = cdx.Extractor{} tests := []struct { - name string - path string - wantErr error - wantInventory []*extractor.Inventory + name string + path string + wantErr error + wantPackages []*extractor.Package }{ { name: "sbom.cdx.json", path: "testdata/sbom.cdx.json", - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "Nginx", Version: "1.21.1", @@ -132,7 +132,7 @@ func TestExtract(t *testing.T) { { name: "sbom.cdx.xml", path: "testdata/sbom.cdx.xml", - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "Nginx", Version: "1.21.1", @@ -181,9 +181,9 @@ func TestExtract(t *testing.T) { t.Errorf("Extract(%s) unexpected error (-want +got):\n%s", tt.path, diff) } - want := tt.wantInventory + want := tt.wantPackages - if diff := cmp.Diff(want, got, cmpopts.SortSlices(invLess)); diff != "" { + if diff := cmp.Diff(want, got, cmpopts.SortSlices(pkgLess)); diff != "" { t.Errorf("Extract(%s) (-want +got):\n%s", tt.path, diff) } }) @@ -198,7 +198,7 @@ func TestToPURL(t *testing.T) { Namespace: "namespace", Version: "1.2.3", } - i := &extractor.Inventory{ + p := &extractor.Package{ Name: "name", Metadata: &cdx.Metadata{ PURL: want, @@ -206,13 +206,13 @@ func TestToPURL(t *testing.T) { }, Locations: []string{"location"}, } - got := e.ToPURL(i) + got := e.ToPURL(p) if diff := cmp.Diff(want, got); diff != "" { - t.Errorf("ToPURL(%v) (-want +got):\n%s", i, diff) + t.Errorf("ToPURL(%v) (-want +got):\n%s", p, diff) } } -func invLess(i1, i2 *extractor.Inventory) bool { +func pkgLess(i1, i2 *extractor.Package) bool { return i1.Name < i2.Name } diff --git a/extractor/filesystem/sbom/spdx/spdx.go b/extractor/filesystem/sbom/spdx/spdx.go index b77f95bc..f010027d 100644 --- a/extractor/filesystem/sbom/spdx/spdx.go +++ b/extractor/filesystem/sbom/spdx/spdx.go @@ -73,7 +73,7 @@ func (e Extractor) FileRequired(api filesystem.FileAPI) bool { } // Extract parses the SPDX SBOM and returns a list purls from the SBOM. -func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { var parseSbom, isSupported = findExtractor(input.Path) if !isSupported { @@ -86,7 +86,7 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] return nil, err } - return e.convertSpdxDocToInventory(spdxDoc, input.Path) + return e.convertSpdxDocToPackage(spdxDoc, input.Path) } func findExtractor(path string) (extractFunc, bool) { @@ -102,28 +102,28 @@ func findExtractor(path string) (extractFunc, bool) { return nil, false } -func (e Extractor) convertSpdxDocToInventory(spdxDoc *spdx.Document, path string) ([]*extractor.Inventory, error) { - results := []*extractor.Inventory{} +func (e Extractor) convertSpdxDocToPackage(spdxDoc *spdx.Document, path string) ([]*extractor.Package, error) { + results := []*extractor.Package{} for _, spdxPkg := range spdxDoc.Packages { - inv := &extractor.Inventory{ + pkg := &extractor.Package{ Locations: []string{path}, Metadata: &Metadata{}, } - m := inv.Metadata.(*Metadata) + m := pkg.Metadata.(*Metadata) for _, extRef := range spdxPkg.PackageExternalReferences { // TODO(b/280991231): Support all RefTypes if extRef.RefType == "cpe23Type" || extRef.RefType == "http://spdx.org/rdf/references/cpe23Type" { m.CPEs = append(m.CPEs, extRef.Locator) - if len(inv.Name) == 0 { - inv.Name = extRef.Locator + if len(pkg.Name) == 0 { + pkg.Name = extRef.Locator } } else if extRef.RefType == "purl" || extRef.RefType == "http://spdx.org/rdf/references/purl" { if m.PURL != nil { log.Warnf("Multiple PURLs found for same package: %q and %q", m.PURL, extRef.Locator) } packageURL, err := purl.FromString(extRef.Locator) - inv.Name = packageURL.Name + pkg.Name = packageURL.Name if err != nil { log.Warnf("Invalid PURL %q for package: %q", extRef.Locator, spdxPkg.PackageName) } else { @@ -131,12 +131,12 @@ func (e Extractor) convertSpdxDocToInventory(spdxDoc *spdx.Document, path string } } } - inv.Metadata = m + pkg.Metadata = m if m.PURL == nil && len(m.CPEs) == 0 { log.Warnf("Neither CPE nor PURL found for package: %+v", spdxPkg) continue } - results = append(results, inv) + results = append(results, pkg) } return results, nil @@ -146,14 +146,14 @@ func hasFileExtension(path string, extension string) bool { return strings.HasSuffix(strings.ToLower(path), extension) } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { - return i.Metadata.(*Metadata).PURL +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { + return p.Metadata.(*Metadata).PURL } // Ecosystem returns the OSV Ecosystem of the software extracted by this extractor. -func (Extractor) Ecosystem(i *extractor.Inventory) string { - purl := i.Metadata.(*Metadata).PURL +func (Extractor) Ecosystem(p *extractor.Package) string { + purl := p.Metadata.(*Metadata).PURL if purl == nil { return "" } diff --git a/extractor/filesystem/sbom/spdx/spdx_test.go b/extractor/filesystem/sbom/spdx/spdx_test.go index 77512b20..a30e9cbb 100644 --- a/extractor/filesystem/sbom/spdx/spdx_test.go +++ b/extractor/filesystem/sbom/spdx/spdx_test.go @@ -97,15 +97,15 @@ func TestExtract(t *testing.T) { var e filesystem.Extractor = spdx.Extractor{} tests := []struct { - name string - path string - wantErr error - wantInventory []*extractor.Inventory + name string + path string + wantErr error + wantPackages []*extractor.Package }{ { name: "sbom.spdx.json", path: "testdata/sbom.spdx.json", - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "cpe:2.3:a:nginx:nginx:1.21.1", Metadata: &spdx.Metadata{ @@ -125,7 +125,7 @@ func TestExtract(t *testing.T) { { name: "purl_and_cpe.spdx.json", path: "testdata/purl_and_cpe.spdx.json", - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "nginx", Metadata: &spdx.Metadata{ @@ -146,7 +146,7 @@ func TestExtract(t *testing.T) { { name: "sbom.spdx", path: "testdata/sbom.spdx", - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "cpe:2.3:a:nginx:nginx:1.21.1", Metadata: &spdx.Metadata{ @@ -166,7 +166,7 @@ func TestExtract(t *testing.T) { { name: "sbom.spdx.yml", path: "testdata/sbom.spdx.yml", - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "cpe:2.3:a:nginx:nginx:1.21.1", Metadata: &spdx.Metadata{ @@ -186,7 +186,7 @@ func TestExtract(t *testing.T) { { name: "sbom.spdx.rdf", path: "testdata/sbom.spdx.rdf", - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "cpe:2.3:a:nginx:nginx:1.21.1", Metadata: &spdx.Metadata{ @@ -234,9 +234,9 @@ func TestExtract(t *testing.T) { t.Errorf("Extract(%s) unexpected error (-want +got):\n%s", tt.path, diff) } - want := tt.wantInventory + want := tt.wantPackages - if diff := cmp.Diff(want, got, cmpopts.SortSlices(invLess)); diff != "" { + if diff := cmp.Diff(want, got, cmpopts.SortSlices(pkgLess)); diff != "" { t.Errorf("Extract(%s) (-want +got):\n%s", tt.path, diff) } }) @@ -251,7 +251,7 @@ func TestToPURL(t *testing.T) { Namespace: "namespace", Version: "1.2.3", } - i := &extractor.Inventory{ + p := &extractor.Package{ Name: "name", Metadata: &spdx.Metadata{ PURL: want, @@ -259,13 +259,13 @@ func TestToPURL(t *testing.T) { }, Locations: []string{"location"}, } - got := e.ToPURL(i) + got := e.ToPURL(p) if diff := cmp.Diff(want, got); diff != "" { - t.Errorf("ToPURL(%v) (-want +got):\n%s", i, diff) + t.Errorf("ToPURL(%v) (-want +got):\n%s", p, diff) } } -func invLess(i1, i2 *extractor.Inventory) bool { +func pkgLess(i1, i2 *extractor.Package) bool { return i1.Name < i2.Name } diff --git a/extractor/standalone/containers/containerd/containerd_dummy.go b/extractor/standalone/containers/containerd/containerd_dummy.go index ad2423b3..155284d7 100644 --- a/extractor/standalone/containers/containerd/containerd_dummy.go +++ b/extractor/standalone/containers/containerd/containerd_dummy.go @@ -40,7 +40,7 @@ func DefaultConfig() Config { // Extractor implements the containerd runtime extractor. type Extractor struct{} -// New creates a new containerd client and returns a containerd container inventory extractor. +// New creates a new containerd client and returns a containerd container package extractor. // No op for non-Linux. func New(cfg Config) standalone.Extractor { return &Extractor{} @@ -66,14 +66,14 @@ func (e Extractor) Version() int { return 0 } func (e Extractor) Requirements() *plugin.Capabilities { return &plugin.Capabilities{} } // Extract is a no-op for non-Linux. -func (e *Extractor) Extract(ctx context.Context, input *standalone.ScanInput) ([]*extractor.Inventory, error) { +func (e *Extractor) Extract(ctx context.Context, input *standalone.ScanInput) ([]*extractor.Package, error) { return nil, fmt.Errorf("only supported on Linux") } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e *Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { +// ToPURL converts a package created by this extractor into a PURL. +func (e *Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { return nil } -// Ecosystem returns no ecosystem since the Inventory is not a software package. -func (e Extractor) Ecosystem(i *extractor.Inventory) string { return "" } +// Ecosystem returns no ecosystem since the Package is not a software package. +func (e Extractor) Ecosystem(p *extractor.Package) string { return "" } diff --git a/extractor/standalone/containers/containerd/containerd_linux.go b/extractor/standalone/containers/containerd/containerd_linux.go index 5f860b72..bf0771d7 100644 --- a/extractor/standalone/containers/containerd/containerd_linux.go +++ b/extractor/standalone/containers/containerd/containerd_linux.go @@ -14,7 +14,7 @@ //go:build linux -// Package containerd extracts container inventory from containerd API. +// Package containerd extracts container package from containerd API. package containerd import ( @@ -77,7 +77,7 @@ type Extractor struct { initNewCtrdClient bool } -// New creates a new containerd client and returns a containerd container inventory extractor. +// New creates a new containerd client and returns a containerd container package extractor. func New(cfg Config) standalone.Extractor { return &Extractor{ client: nil, @@ -126,12 +126,12 @@ func (e Extractor) Requirements() *plugin.Capabilities { } // Extractor extracts containers from the containerd API. -func (e *Extractor) Extract(ctx context.Context, input *standalone.ScanInput) ([]*extractor.Inventory, error) { - var inventory = []*extractor.Inventory{} +func (e *Extractor) Extract(ctx context.Context, input *standalone.ScanInput) ([]*extractor.Package, error) { + var result = []*extractor.Package{} if e.checkIfSocketExists { if _, err := os.Stat(e.socketAddr); err != nil { log.Infof("Containerd socket %v does not exist, skipping extraction.", e.socketAddr) - return inventory, err + return result, err } } // Creating client here instead of New() to prevent client creation when extractor is not in use. @@ -141,34 +141,34 @@ func (e *Extractor) Extract(ctx context.Context, input *standalone.ScanInput) ([ cli, err := containerd.New(e.socketAddr) if err != nil { log.Errorf("Failed to connect to containerd socket %v, error: %v", e.socketAddr, err) - return inventory, err + return result, err } e.client = cli e.initNewCtrdClient = false } if e.client == nil { - return inventory, fmt.Errorf("Containerd API client is not initialized") + return result, fmt.Errorf("Containerd API client is not initialized") } ctrMetadata, err := containersFromAPI(ctx, e.client) if err != nil { - log.Errorf("Could not get container inventory from the containerd: %v", err) - return inventory, err + log.Errorf("Could not get container package from the containerd: %v", err) + return result, err } for _, ctr := range ctrMetadata { - pkg := &extractor.Inventory{ + pkg := &extractor.Package{ Name: ctr.ImageName, Version: ctr.ImageDigest, Locations: []string{ctr.RootFS}, Metadata: &ctr, } - inventory = append(inventory, pkg) + result = append(result, pkg) } defer e.client.Close() - return inventory, nil + return result, nil } func containersFromAPI(ctx context.Context, client CtrdClient) ([]Metadata, error) { @@ -294,10 +294,10 @@ func taskMetadata(ctx context.Context, client CtrdClient, task *task.Process, na return md, nil } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { return nil } -// Ecosystem returns no ecosystem since the Inventory is not a software package. -func (e Extractor) Ecosystem(i *extractor.Inventory) string { return "" } +// Ecosystem returns no ecosystem since the Package is not a software package. +func (e Extractor) Ecosystem(p *extractor.Package) string { return "" } diff --git a/extractor/standalone/containers/containerd/containerd_test.go b/extractor/standalone/containers/containerd/containerd_test.go index 05b1d40e..e57e9516 100644 --- a/extractor/standalone/containers/containerd/containerd_test.go +++ b/extractor/standalone/containers/containerd/containerd_test.go @@ -36,21 +36,21 @@ import ( func TestExtract(t *testing.T) { tests := []struct { - name string - onGoos []string - nssTaskIds map[string][]string - tsks []*task.Process - ctrs []containerd.Container - wantInventory []*extractor.Inventory - wantErr error + name string + onGoos []string + nssTaskIds map[string][]string + tsks []*task.Process + ctrs []containerd.Container + wantPackages []*extractor.Package + wantErr error }{ { - name: "valid with no tasks", - onGoos: []string{"linux"}, - nssTaskIds: map[string][]string{"default": {}, "k8s.io": {}}, - tsks: []*task.Process{}, - ctrs: []containerd.Container{}, - wantInventory: []*extractor.Inventory{}, + name: "valid with no tasks", + onGoos: []string{"linux"}, + nssTaskIds: map[string][]string{"default": {}, "k8s.io": {}}, + tsks: []*task.Process{}, + ctrs: []containerd.Container{}, + wantPackages: []*extractor.Package{}, }, { name: "valid with tasks and rootfs", @@ -58,7 +58,7 @@ func TestExtract(t *testing.T) { nssTaskIds: map[string][]string{"default": {"123456789"}, "k8s.io": {"567890123"}}, tsks: []*task.Process{{ID: "123456789", ContainerID: "", Pid: 12345}, {ID: "567890123", ContainerID: "", Pid: 5678}}, ctrs: []containerd.Container{fakeclient.NewFakeContainer("123456789", "image1", "digest1", "/run/containerd/io.containerd.runtime.v2.task/default/123456789/rootfs"), fakeclient.NewFakeContainer("567890123", "image2", "digest2", "/run/containerd/io.containerd.runtime.v2.task/k8s.io/567890123/rootfs")}, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "image1", Version: "digest1", @@ -95,7 +95,7 @@ func TestExtract(t *testing.T) { nssTaskIds: map[string][]string{"default": {"123456789"}, "k8s.io": {"567890123"}}, tsks: []*task.Process{{ID: "123456789", ContainerID: "", Pid: 12345}, {ID: "567890123", ContainerID: "", Pid: 5678}}, ctrs: []containerd.Container{fakeclient.NewFakeContainer("123456789", "image1", "digest1", ""), fakeclient.NewFakeContainer("567890123", "image2", "digest2", "")}, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "image1", Version: "digest1", @@ -132,7 +132,7 @@ func TestExtract(t *testing.T) { nssTaskIds: map[string][]string{"default": {"123456788"}, "k8s.io": {"567890122"}}, tsks: []*task.Process{{ID: "123456788", ContainerID: "", Pid: 12346}, {ID: "567890122", ContainerID: "", Pid: 5677}}, ctrs: []containerd.Container{fakeclient.NewFakeContainer("123456788", "image1", "digest1", "test/rootfs"), fakeclient.NewFakeContainer("567890122", "image2", "digest2", "test2/rootfs")}, - wantInventory: []*extractor.Inventory{ + wantPackages: []*extractor.Package{ { Name: "image1", Version: "digest1", @@ -185,7 +185,7 @@ func TestExtract(t *testing.T) { ignoreOrder := cmpopts.SortSlices(func(a, b any) bool { return fmt.Sprintf("%+v", a) < fmt.Sprintf("%+v", b) }) - if diff := cmp.Diff(tt.wantInventory, got, ignoreOrder); diff != "" { + if diff := cmp.Diff(tt.wantPackages, got, ignoreOrder); diff != "" { t.Errorf("Extract(%s) (-want +got):\n%s", tt.name, diff) } }) diff --git a/extractor/standalone/os/netports/netports_dummy.go b/extractor/standalone/os/netports/netports_dummy.go index a7244217..7a2db3eb 100644 --- a/extractor/standalone/os/netports/netports_dummy.go +++ b/extractor/standalone/os/netports/netports_dummy.go @@ -51,14 +51,14 @@ func (e Extractor) Requirements() *plugin.Capabilities { } // Extract is a no-op for non Linux. -func (e *Extractor) Extract(ctx context.Context, input *standalone.ScanInput) ([]*extractor.Inventory, error) { +func (e *Extractor) Extract(ctx context.Context, input *standalone.ScanInput) ([]*extractor.Package, error) { return nil, fmt.Errorf("only supported on Linux") } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e *Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { +// ToPURL converts a package created by this extractor into a PURL. +func (e *Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { return nil } // Ecosystem returns no ecosystem. -func (Extractor) Ecosystem(i *extractor.Inventory) string { return "" } +func (Extractor) Ecosystem(p *extractor.Package) string { return "" } diff --git a/extractor/standalone/os/netports/netports_linux.go b/extractor/standalone/os/netports/netports_linux.go index ef4a763d..6b4ab2b9 100644 --- a/extractor/standalone/os/netports/netports_linux.go +++ b/extractor/standalone/os/netports/netports_linux.go @@ -70,7 +70,7 @@ func (e Extractor) Requirements() *plugin.Capabilities { } // Extract extracts open ports on the system. -func (e Extractor) Extract(ctx context.Context, input *standalone.ScanInput) ([]*extractor.Inventory, error) { +func (e Extractor) Extract(ctx context.Context, input *standalone.ScanInput) ([]*extractor.Package, error) { // First, extract a mapping that provides the PID for each open socket inode number. inodeToPID, err := proc.MapSocketInodesToPID(ctx, input.Root, input.FS) if err != nil { @@ -85,7 +85,7 @@ func (e Extractor) Extract(ctx context.Context, input *standalone.ScanInput) ([] // Maps socket inode -> PID -> command line. Tries to cache the command line when possible. pidCommandLinesCache := make(map[int64][]string) - var inventories []*extractor.Inventory + var packages []*extractor.Package proto := "tcp" for _, tcpInfo := range tcpInfos { @@ -93,13 +93,13 @@ func (e Extractor) Extract(ctx context.Context, input *standalone.ScanInput) ([] port := entry.LocalPort pid, ok := inodeToPID[entry.Inode] if !ok { - inventories = append(inventories, e.newInventory(ctx, port, proto, []string{"unknown"})) + packages = append(packages, e.newPackage(ctx, port, proto, []string{"unknown"})) continue } cmdline, cached := pidCommandLinesCache[pid] if cached { - inventories = append(inventories, e.newInventory(ctx, port, proto, cmdline)) + packages = append(packages, e.newPackage(ctx, port, proto, cmdline)) continue } @@ -109,21 +109,21 @@ func (e Extractor) Extract(ctx context.Context, input *standalone.ScanInput) ([] } pidCommandLinesCache[pid] = cmdline - inventories = append(inventories, e.newInventory(ctx, port, proto, cmdline)) + packages = append(packages, e.newPackage(ctx, port, proto, cmdline)) } } - return inventories, nil + return packages, nil } -// ToPURL converts an inventory created by this extractor into a PURL. +// ToPURL converts a package created by this extractor into a PURL. // This extractor does not create PURLs. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { return nil } // Ecosystem returns no Ecosystem since the ecosystem is not known by OSV yet. -func (Extractor) Ecosystem(i *extractor.Inventory) string { return "" } +func (Extractor) Ecosystem(p *extractor.Package) string { return "" } func (e Extractor) allTCPInfo(ctx context.Context) ([]*proc.NetTCPInfo, error) { var entries []*proc.NetTCPInfo @@ -150,8 +150,8 @@ func (e Extractor) extractPortsFromFile(ctx context.Context, path string) (*proc return proc.ParseNetTCP(ctx, f) } -func (e Extractor) newInventory(ctx context.Context, port uint32, protocol string, cmdline []string) *extractor.Inventory { - return &extractor.Inventory{ +func (e Extractor) newPackage(ctx context.Context, port uint32, protocol string, cmdline []string) *extractor.Package { + return &extractor.Package{ Name: fmt.Sprintf("network-port-%d", port), Metadata: &Metadata{ Port: port, diff --git a/extractor/standalone/standalone.go b/extractor/standalone/standalone.go index ce37f4e7..d1ed9c38 100644 --- a/extractor/standalone/standalone.go +++ b/extractor/standalone/standalone.go @@ -29,7 +29,7 @@ import ( type Extractor interface { extractor.Extractor // Extract the information. - Extract(ctx context.Context, input *ScanInput) ([]*extractor.Inventory, error) + Extract(ctx context.Context, input *ScanInput) ([]*extractor.Package, error) } // Config for running standalone extractors. @@ -47,8 +47,8 @@ type ScanInput struct { } // Run the extractors that are specified in the config. -func Run(ctx context.Context, config *Config) ([]*extractor.Inventory, []*plugin.Status, error) { - var inventories []*extractor.Inventory +func Run(ctx context.Context, config *Config) ([]*extractor.Package, []*plugin.Status, error) { + var packages []*extractor.Package var statuses []*plugin.Status if !config.ScanRoot.IsVirtual() { @@ -69,18 +69,18 @@ func Run(ctx context.Context, config *Config) ([]*extractor.Inventory, []*plugin return nil, nil, ctx.Err() } - inv, err := extractor.Extract(ctx, scanInput) + pkg, err := extractor.Extract(ctx, scanInput) if err != nil { statuses = append(statuses, plugin.StatusFromErr(extractor, false, err)) continue } - for _, i := range inv { - i.Extractor = extractor + for _, p := range pkg { + p.Extractor = extractor } - inventories = append(inventories, inv...) + packages = append(packages, pkg...) statuses = append(statuses, plugin.StatusFromErr(extractor, false, nil)) } - return inventories, statuses, nil + return packages, statuses, nil } diff --git a/extractor/standalone/windows/common/metadata/metadata.go b/extractor/standalone/windows/common/metadata/metadata.go index 2a3816e7..4930eaef 100644 --- a/extractor/standalone/windows/common/metadata/metadata.go +++ b/extractor/standalone/windows/common/metadata/metadata.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -// Package metadata provides metadata structures to annotate Windows inventories. +// Package metadata provides metadata structures to annotate Windows packages. package metadata // OSVersion provides metadata about the OS version. diff --git a/extractor/standalone/windows/dismpatch/dismparser/dism_parser.go b/extractor/standalone/windows/dismpatch/dismparser/dism_parser.go index e54e676b..0dd9e198 100644 --- a/extractor/standalone/windows/dismpatch/dismparser/dism_parser.go +++ b/extractor/standalone/windows/dismpatch/dismparser/dism_parser.go @@ -37,9 +37,9 @@ type DismPkg struct { InstallTime string } -// Parse parses dism output into an array of dismPkgs. +// Parse parses dism output into an array of dismPackages. func Parse(input string) ([]DismPkg, string, error) { - pkgs := strings.Split(input, "Package Id") + packages := strings.Split(input, "Package Id") pkgExp, err := regexp.Compile("entity :(.*)\n*State :(.*)\n*Release Type :(.*)\n*Install Time :(.*)\n*") if err != nil { @@ -52,9 +52,9 @@ func Parse(input string) ([]DismPkg, string, error) { } imgVersion := "" - dismPkgs := []DismPkg{} + dismPackages := []DismPkg{} - for _, pkg := range pkgs { + for _, pkg := range packages { matches := pkgExp.FindStringSubmatch(pkg) if len(matches) > 4 { dismPkg := DismPkg{ @@ -64,7 +64,7 @@ func Parse(input string) ([]DismPkg, string, error) { InstallTime: strings.TrimSpace(matches[4]), } dismPkg.PackageVersion = findVersion(dismPkg.PackageIdentity) - dismPkgs = append(dismPkgs, dismPkg) + dismPackages = append(dismPackages, dismPkg) } else { // this is the first entry that has the image version matches = imgExp.FindStringSubmatch(pkg) @@ -74,11 +74,11 @@ func Parse(input string) ([]DismPkg, string, error) { } } - if len(dismPkgs) == 0 { + if len(dismPackages) == 0 { return nil, "", ErrParsingError } - return dismPkgs, imgVersion, nil + return dismPackages, imgVersion, nil } func findVersion(identity string) string { diff --git a/extractor/standalone/windows/dismpatch/dismparser/dism_parser_test.go b/extractor/standalone/windows/dismpatch/dismparser/dism_parser_test.go index d3b8d63d..a8619a7c 100644 --- a/extractor/standalone/windows/dismpatch/dismparser/dism_parser_test.go +++ b/extractor/standalone/windows/dismpatch/dismparser/dism_parser_test.go @@ -27,7 +27,7 @@ func TestParse(t *testing.T) { t.Fatalf("Failed to read testdata: %v", err) } - pkgs, imgVersion, err := Parse(string(content)) + packages, imgVersion, err := Parse(string(content)) if err != nil { t.Errorf("Error while parsing the output: %v", err) } @@ -81,7 +81,7 @@ func TestParse(t *testing.T) { }, } - if diff := cmp.Diff(want, pkgs); diff != "" { + if diff := cmp.Diff(want, packages); diff != "" { t.Errorf("Parse: Diff = %v", diff) } } diff --git a/extractor/standalone/windows/dismpatch/dismpatch.go b/extractor/standalone/windows/dismpatch/dismpatch.go index 014e679b..091a6836 100644 --- a/extractor/standalone/windows/dismpatch/dismpatch.go +++ b/extractor/standalone/windows/dismpatch/dismpatch.go @@ -24,8 +24,8 @@ import ( "github.com/google/osv-scalibr/purl" ) -// inventoryFromOutput parses the output of DISM and produces inventory entries from it. -func inventoryFromOutput(flavor, output string) ([]*extractor.Inventory, error) { +// packageFromOutput parses the output of DISM and produces package entries from it. +func packageFromOutput(flavor, output string) ([]*extractor.Package, error) { packages, imgVersion, err := dismparser.Parse(output) if err != nil { return nil, err @@ -33,7 +33,7 @@ func inventoryFromOutput(flavor, output string) ([]*extractor.Inventory, error) imgVersion = strings.TrimSpace(imgVersion) windowsProduct := winproducts.WindowsProductFromVersion(flavor, imgVersion) - inventory := []*extractor.Inventory{ + result := []*extractor.Package{ { Name: windowsProduct, Version: imgVersion, @@ -46,33 +46,33 @@ func inventoryFromOutput(flavor, output string) ([]*extractor.Inventory, error) // extract KB informations for _, pkg := range packages { - inventory = append(inventory, &extractor.Inventory{ + result = append(result, &extractor.Package{ Name: pkg.PackageIdentity, Version: pkg.PackageVersion, }) } - return inventory, nil + return result, nil } // Ecosystem returns no ecosystem since OSV does ont support dism patches yet. -func (Extractor) Ecosystem(i *extractor.Inventory) string { return "" } +func (Extractor) Ecosystem(p *extractor.Package) string { return "" } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(pkg *extractor.Package) *purl.PackageURL { p := &purl.PackageURL{ Type: purl.TypeGeneric, Namespace: "microsoft", - Name: i.Name, + Name: pkg.Name, } - switch i.Metadata.(type) { + switch pkg.Metadata.(type) { case *metadata.OSVersion: p.Qualifiers = purl.QualifiersFromMap(map[string]string{ - purl.BuildNumber: i.Metadata.(*metadata.OSVersion).FullVersion, + purl.BuildNumber: pkg.Metadata.(*metadata.OSVersion).FullVersion, }) default: - p.Version = i.Version + p.Version = pkg.Version } return p diff --git a/extractor/standalone/windows/dismpatch/dismpatch_dummy.go b/extractor/standalone/windows/dismpatch/dismpatch_dummy.go index e979001c..8d3a0acc 100644 --- a/extractor/standalone/windows/dismpatch/dismpatch_dummy.go +++ b/extractor/standalone/windows/dismpatch/dismpatch_dummy.go @@ -46,6 +46,6 @@ func (e Extractor) Version() int { return 0 } func (e Extractor) Requirements() *plugin.Capabilities { return &plugin.Capabilities{} } // Extract is a no-op for Linux. -func (e *Extractor) Extract(ctx context.Context, input *standalone.ScanInput) ([]*extractor.Inventory, error) { +func (e *Extractor) Extract(ctx context.Context, input *standalone.ScanInput) ([]*extractor.Package, error) { return nil, fmt.Errorf("only supported on Windows") } diff --git a/extractor/standalone/windows/dismpatch/dismpatch_test.go b/extractor/standalone/windows/dismpatch/dismpatch_test.go index 56c0f16b..cc29e040 100644 --- a/extractor/standalone/windows/dismpatch/dismpatch_test.go +++ b/extractor/standalone/windows/dismpatch/dismpatch_test.go @@ -25,7 +25,7 @@ import ( "github.com/google/osv-scalibr/extractor/standalone/windows/dismpatch/dismparser" ) -func TestInventoryFromOutput(t *testing.T) { +func TestPackageFromOutput(t *testing.T) { dismTestData, err := os.ReadFile("dismparser/testdata/dism_testdata.txt") if err != nil { t.Fatalf("Failed to read testdata: %v", err) @@ -35,14 +35,14 @@ func TestInventoryFromOutput(t *testing.T) { desc string flavor string output string - want []*extractor.Inventory + want []*extractor.Package wantErr error }{ { - desc: "Valid test data returns inventory", + desc: "Valid test data returns package", flavor: "server", output: string(dismTestData), - want: []*extractor.Inventory{ + want: []*extractor.Package{ { Name: "windows_server_2019", Version: "10.0.17763.3406", @@ -89,9 +89,9 @@ func TestInventoryFromOutput(t *testing.T) { for _, tc := range tests { t.Run(tc.desc, func(t *testing.T) { - got, gotErr := inventoryFromOutput(tc.flavor, tc.output) + got, gotErr := packageFromOutput(tc.flavor, tc.output) if gotErr != tc.wantErr { - t.Fatalf("inventoryFromOutput(%q, %q) returned an unexpected error: %v", tc.flavor, tc.output, gotErr) + t.Fatalf("packageFromOutput(%q, %q) returned an unexpected error: %v", tc.flavor, tc.output, gotErr) } if tc.wantErr != nil { @@ -99,7 +99,7 @@ func TestInventoryFromOutput(t *testing.T) { } if diff := cmp.Diff(tc.want, got); diff != "" { - t.Errorf("inventoryFromOutput(%q, %q) returned an unexpected diff (-want +got): %v", tc.flavor, tc.output, diff) + t.Errorf("packageFromOutput(%q, %q) returned an unexpected diff (-want +got): %v", tc.flavor, tc.output, diff) } }) } diff --git a/extractor/standalone/windows/dismpatch/dismpatch_windows.go b/extractor/standalone/windows/dismpatch/dismpatch_windows.go index a6f8cc75..3f744837 100644 --- a/extractor/standalone/windows/dismpatch/dismpatch_windows.go +++ b/extractor/standalone/windows/dismpatch/dismpatch_windows.go @@ -53,7 +53,7 @@ func (e Extractor) Requirements() *plugin.Capabilities { } // Extract retrieves the patch level from the DISM command line tool. -func (e *Extractor) Extract(ctx context.Context, input *standalone.ScanInput) ([]*extractor.Inventory, error) { +func (e *Extractor) Extract(ctx context.Context, input *standalone.ScanInput) ([]*extractor.Package, error) { opener := registry.NewLiveOpener() reg, err := opener.Open() if err != nil { @@ -67,7 +67,7 @@ func (e *Extractor) Extract(ctx context.Context, input *standalone.ScanInput) ([ } flavor := winproducts.WindowsFlavorFromRegistry(reg) - return inventoryFromOutput(flavor, output) + return packageFromOutput(flavor, output) } // runDISM executes the dism command line tool. diff --git a/extractor/standalone/windows/ospackages/ospackages_dummy.go b/extractor/standalone/windows/ospackages/ospackages_dummy.go index f993f50c..eb025db3 100644 --- a/extractor/standalone/windows/ospackages/ospackages_dummy.go +++ b/extractor/standalone/windows/ospackages/ospackages_dummy.go @@ -62,15 +62,15 @@ func (e Extractor) Version() int { return 0 } func (e Extractor) Requirements() *plugin.Capabilities { return &plugin.Capabilities{} } // Extract is a no-op for Linux. -func (e *Extractor) Extract(ctx context.Context, input *standalone.ScanInput) ([]*extractor.Inventory, error) { +func (e *Extractor) Extract(ctx context.Context, input *standalone.ScanInput) ([]*extractor.Package, error) { return nil, fmt.Errorf("only supported on Windows") } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e *Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { +// ToPURL converts a package created by this extractor into a PURL. +func (e *Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { log.Warnf("Trying to use ospackages on %s, which is not supported", runtime.GOOS) return nil } // Ecosystem returns no ecosystem since OSV does not support windows ospackages yet. -func (Extractor) Ecosystem(i *extractor.Inventory) string { return "" } +func (Extractor) Ecosystem(p *extractor.Package) string { return "" } diff --git a/extractor/standalone/windows/ospackages/ospackages_windows.go b/extractor/standalone/windows/ospackages/ospackages_windows.go index 5986466a..11052457 100644 --- a/extractor/standalone/windows/ospackages/ospackages_windows.go +++ b/extractor/standalone/windows/ospackages/ospackages_windows.go @@ -84,7 +84,7 @@ func (e Extractor) Requirements() *plugin.Capabilities { } // Extract retrieves the patch level from the Windows registry. -func (e *Extractor) Extract(ctx context.Context, input *standalone.ScanInput) ([]*extractor.Inventory, error) { +func (e *Extractor) Extract(ctx context.Context, input *standalone.ScanInput) ([]*extractor.Package, error) { reg, err := e.opener.Open() if err != nil { return nil, err @@ -98,7 +98,7 @@ func (e *Extractor) Extract(ctx context.Context, input *standalone.ScanInput) ([ return nil, err } - inventory := e.allSoftwaresInfo(reg, "HKLM", sysKeys) + pkg := e.allSoftwaresInfo(reg, "HKLM", sysKeys) // Then we extract user-level installed software. userKeys, err := e.installedUserSoftware(reg) @@ -106,27 +106,27 @@ func (e *Extractor) Extract(ctx context.Context, input *standalone.ScanInput) ([ return nil, err } - inv := e.allSoftwaresInfo(reg, "HKU", userKeys) - return append(inventory, inv...), nil + pkgs := e.allSoftwaresInfo(reg, "HKU", userKeys) + return append(pkgs, pkg...), nil } -// allSoftwaresInfo builds the inventory of name/version for installed software from the given registry +// allSoftwaresInfo builds the package of name/version for installed software from the given registry // keys. This function cannot return an error. -func (e *Extractor) allSoftwaresInfo(reg registry.Registry, hive string, paths []string) []*extractor.Inventory { - var inventory []*extractor.Inventory +func (e *Extractor) allSoftwaresInfo(reg registry.Registry, hive string, paths []string) []*extractor.Package { + var pkgs []*extractor.Package for _, p := range paths { // Silently swallow errors as some software might not have a name or version. // For example, paint will be a subkey of the registry key, but it does not have a version. - if inv, err := e.softwareInfo(reg, hive, p); err == nil { - inventory = append(inventory, inv) + if pkg, err := e.softwareInfo(reg, hive, p); err == nil { + pkgs = append(pkgs, pkg) } } - return inventory + return pkgs } -func (e *Extractor) softwareInfo(reg registry.Registry, hive string, path string) (*extractor.Inventory, error) { +func (e *Extractor) softwareInfo(reg registry.Registry, hive string, path string) (*extractor.Package, error) { key, err := reg.OpenKey(hive, path) if err != nil { return nil, err @@ -143,7 +143,7 @@ func (e *Extractor) softwareInfo(reg registry.Registry, hive string, path string return nil, err } - return &extractor.Inventory{ + return &extractor.Package{ Name: displayName, Version: displayVersion, }, nil @@ -205,23 +205,23 @@ func (e *Extractor) enumerateSubkeys(reg registry.Registry, hive string, path st return paths, nil } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { - if strings.HasPrefix(i.Name, googetPrefix) { +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { + if strings.HasPrefix(p.Name, googetPrefix) { return &purl.PackageURL{ Type: purl.TypeGooget, - Name: i.Name, - Version: i.Version, + Name: p.Name, + Version: p.Version, } } return &purl.PackageURL{ Type: purl.TypeGeneric, Namespace: "microsoft", - Name: i.Name, - Version: i.Version, + Name: p.Name, + Version: p.Version, } } // Ecosystem returns no ecosystem since OSV does not support windows ospackages yet. -func (Extractor) Ecosystem(i *extractor.Inventory) string { return "" } +func (Extractor) Ecosystem(p *extractor.Package) string { return "" } diff --git a/extractor/standalone/windows/ospackages/ospackages_windows_test.go b/extractor/standalone/windows/ospackages/ospackages_windows_test.go index 018ffdb3..cffe0f6b 100644 --- a/extractor/standalone/windows/ospackages/ospackages_windows_test.go +++ b/extractor/standalone/windows/ospackages/ospackages_windows_test.go @@ -39,7 +39,7 @@ func TestExtract(t *testing.T) { tests := []struct { name string reg *mockregistry.MockRegistry - want []*extractor.Inventory + want []*extractor.Package wantErr bool }{ { @@ -102,7 +102,7 @@ func TestExtract(t *testing.T) { }, }, }, - want: []*extractor.Inventory{ + want: []*extractor.Package{ {Name: "Some software install", Version: "1.0.0"}, {Name: "Some software install wow64", Version: "1.4.0"}, }, @@ -174,7 +174,7 @@ func TestExtract(t *testing.T) { }, }, }, - want: []*extractor.Inventory{ + want: []*extractor.Package{ {Name: "Some software install for user00", Version: "1.00.1"}, {Name: "Some software install for user01", Version: "1.01.1"}, }, @@ -182,7 +182,7 @@ func TestExtract(t *testing.T) { { name: "empty_registry_returns_error", reg: &mockregistry.MockRegistry{}, - want: []*extractor.Inventory{}, + want: []*extractor.Package{}, wantErr: true, }, } @@ -210,17 +210,17 @@ func TestExtract(t *testing.T) { func TestToPURL(t *testing.T) { tests := []struct { name string - inv *extractor.Inventory + pkg *extractor.Package want *purl.PackageURL }{ { name: "googet_package", - inv: &extractor.Inventory{Name: "GooGet - some package", Version: "1.0.0"}, + pkg: &extractor.Package{Name: "GooGet - some package", Version: "1.0.0"}, want: &purl.PackageURL{Type: purl.TypeGooget, Name: "GooGet - some package", Version: "1.0.0"}, }, { name: "normal_windows_package", - inv: &extractor.Inventory{Name: "Some software", Version: "1.0.0"}, + pkg: &extractor.Package{Name: "Some software", Version: "1.0.0"}, want: &purl.PackageURL{Type: purl.TypeGeneric, Namespace: "microsoft", Name: "Some software", Version: "1.0.0"}, }, } @@ -228,9 +228,9 @@ func TestToPURL(t *testing.T) { for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { e := Extractor{} - got := e.ToPURL(tc.inv) + got := e.ToPURL(tc.pkg) if diff := cmp.Diff(tc.want, got); diff != "" { - t.Errorf("ToPURL(%v) returned an unexpected diff (-want +got): %v", tc.inv, diff) + t.Errorf("ToPURL(%v) returned an unexpected diff (-want +got): %v", tc.pkg, diff) } }) } diff --git a/extractor/standalone/windows/regosversion/regosversion_dummy.go b/extractor/standalone/windows/regosversion/regosversion_dummy.go index 010d0619..7f9cc199 100644 --- a/extractor/standalone/windows/regosversion/regosversion_dummy.go +++ b/extractor/standalone/windows/regosversion/regosversion_dummy.go @@ -62,15 +62,15 @@ func (e Extractor) Version() int { return 0 } func (e Extractor) Requirements() *plugin.Capabilities { return &plugin.Capabilities{} } // Extract is a no-op for non-Windows platforms. -func (e *Extractor) Extract(ctx context.Context, input *standalone.ScanInput) ([]*extractor.Inventory, error) { +func (e *Extractor) Extract(ctx context.Context, input *standalone.ScanInput) ([]*extractor.Package, error) { return nil, fmt.Errorf("only supported on Windows") } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e *Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { +// ToPURL converts a package created by this extractor into a PURL. +func (e *Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { log.Warnf("Trying to use regosversion on %s, which is not supported", runtime.GOOS) return nil } // Ecosystem returns no ecosystem since OSV does not support windows regosversion yet. -func (Extractor) Ecosystem(i *extractor.Inventory) string { return "" } +func (Extractor) Ecosystem(p *extractor.Package) string { return "" } diff --git a/extractor/standalone/windows/regosversion/regosversion_windows.go b/extractor/standalone/windows/regosversion/regosversion_windows.go index febbfd95..157d0fd3 100644 --- a/extractor/standalone/windows/regosversion/regosversion_windows.go +++ b/extractor/standalone/windows/regosversion/regosversion_windows.go @@ -79,7 +79,7 @@ func (e Extractor) Requirements() *plugin.Capabilities { } // Extract the DISM patch level on Windows. -func (e *Extractor) Extract(ctx context.Context, input *standalone.ScanInput) ([]*extractor.Inventory, error) { +func (e *Extractor) Extract(ctx context.Context, input *standalone.ScanInput) ([]*extractor.Package, error) { reg, err := e.opener.Open() if err != nil { return nil, err @@ -111,7 +111,7 @@ func (e *Extractor) Extract(ctx context.Context, input *standalone.ScanInput) ([ flavor := winproducts.WindowsFlavorFromRegistry(reg) fullVersion := fmt.Sprintf("%s.%s.%s", currentVersion, buildNumber, revision) winproduct := winproducts.WindowsProductFromVersion(flavor, fullVersion) - return []*extractor.Inventory{ + return []*extractor.Package{ { Name: winproduct, Version: fullVersion, @@ -158,14 +158,14 @@ func (e Extractor) windowsRevision(key registry.Key) (string, error) { return buildLabParts[1], nil } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { var qualifiers purl.Qualifiers - switch i.Metadata.(type) { + switch p.Metadata.(type) { case metadata.OSVersion: qualifiers = purl.QualifiersFromMap(map[string]string{ - purl.BuildNumber: i.Metadata.(metadata.OSVersion).FullVersion, + purl.BuildNumber: p.Metadata.(metadata.OSVersion).FullVersion, }) default: return nil @@ -174,10 +174,10 @@ func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { return &purl.PackageURL{ Type: purl.TypeGeneric, Namespace: "microsoft", - Name: i.Name, + Name: p.Name, Qualifiers: qualifiers, } } // Ecosystem returns no ecosystem since OSV does not support windows regosversion yet. -func (Extractor) Ecosystem(i *extractor.Inventory) string { return "" } +func (Extractor) Ecosystem(p *extractor.Package) string { return "" } diff --git a/extractor/standalone/windows/regosversion/regosversion_windows_test.go b/extractor/standalone/windows/regosversion/regosversion_windows_test.go index cbe06594..bb0f8b2e 100644 --- a/extractor/standalone/windows/regosversion/regosversion_windows_test.go +++ b/extractor/standalone/windows/regosversion/regosversion_windows_test.go @@ -31,7 +31,7 @@ func TestExtract(t *testing.T) { tests := []struct { name string reg *mockregistry.MockRegistry - want []*extractor.Inventory + want []*extractor.Package wantErr bool }{ { @@ -65,7 +65,7 @@ func TestExtract(t *testing.T) { }, }, }, - want: []*extractor.Inventory{ + want: []*extractor.Package{ { Name: "windows_11:21H2", Version: "10.0.22000.1234", @@ -107,7 +107,7 @@ func TestExtract(t *testing.T) { }, }, }, - want: []*extractor.Inventory{ + want: []*extractor.Package{ { Name: "unknownWindows", Version: "10.0.12345.1234", @@ -145,7 +145,7 @@ func TestExtract(t *testing.T) { }, }, }, - want: []*extractor.Inventory{ + want: []*extractor.Package{ { Name: "windows_xp", Version: "5.1.2600.1234", @@ -183,7 +183,7 @@ func TestExtract(t *testing.T) { }, }, }, - want: []*extractor.Inventory{ + want: []*extractor.Package{ { Name: "unknownWindows", Version: "5.1.1234.1234", diff --git a/extractor/standalone/windows/regpatchlevel/regpatchlevel_dummy.go b/extractor/standalone/windows/regpatchlevel/regpatchlevel_dummy.go index 501e6eca..4f47c4f2 100644 --- a/extractor/standalone/windows/regpatchlevel/regpatchlevel_dummy.go +++ b/extractor/standalone/windows/regpatchlevel/regpatchlevel_dummy.go @@ -62,15 +62,15 @@ func (e Extractor) Version() int { return 0 } func (e Extractor) Requirements() *plugin.Capabilities { return &plugin.Capabilities{} } // Extract is a no-op for Linux. -func (e *Extractor) Extract(ctx context.Context, input *standalone.ScanInput) ([]*extractor.Inventory, error) { +func (e *Extractor) Extract(ctx context.Context, input *standalone.ScanInput) ([]*extractor.Package, error) { return nil, fmt.Errorf("only supported on Windows") } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e *Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { +// ToPURL converts a package created by this extractor into a PURL. +func (e *Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { log.Warnf("Trying to use regpatchlevel on %s, which is not supported", runtime.GOOS) return nil } // Ecosystem returns no ecosystem since OSV does not support windows regpatchlevel yet. -func (Extractor) Ecosystem(i *extractor.Inventory) string { return "" } +func (Extractor) Ecosystem(p *extractor.Package) string { return "" } diff --git a/extractor/standalone/windows/regpatchlevel/regpatchlevel_windows.go b/extractor/standalone/windows/regpatchlevel/regpatchlevel_windows.go index 86940d2c..814d8e32 100644 --- a/extractor/standalone/windows/regpatchlevel/regpatchlevel_windows.go +++ b/extractor/standalone/windows/regpatchlevel/regpatchlevel_windows.go @@ -85,7 +85,7 @@ func (e Extractor) Requirements() *plugin.Capabilities { } // Extract retrieves the patch level from the Windows registry. -func (e *Extractor) Extract(ctx context.Context, input *standalone.ScanInput) ([]*extractor.Inventory, error) { +func (e *Extractor) Extract(ctx context.Context, input *standalone.ScanInput) ([]*extractor.Package, error) { reg, err := e.opener.Open() if err != nil { return nil, err @@ -103,7 +103,7 @@ func (e *Extractor) Extract(ctx context.Context, input *standalone.ScanInput) ([ return nil, err } - var inventory []*extractor.Inventory + var pkgs []*extractor.Package for _, subkey := range subkeys { entry, err := e.handleKey(reg, regPackagesRoot, subkey) @@ -115,13 +115,13 @@ func (e *Extractor) Extract(ctx context.Context, input *standalone.ScanInput) ([ return nil, err } - inventory = append(inventory, entry) + pkgs = append(pkgs, entry) } - return inventory, nil + return pkgs, nil } -func (e *Extractor) handleKey(reg registry.Registry, registryPath, keyName string) (*extractor.Inventory, error) { +func (e *Extractor) handleKey(reg registry.Registry, registryPath, keyName string) (*extractor.Package, error) { keyPath := fmt.Sprintf("%s\\%s", registryPath, keyName) key, err := reg.OpenKey("HKLM", keyPath) if err != nil { @@ -149,21 +149,21 @@ func (e *Extractor) handleKey(reg registry.Registry, registryPath, keyName strin return nil, errSkipEntry } - return &extractor.Inventory{ + return &extractor.Package{ Name: keyName, Version: submatch[1], }, nil } -// ToPURL converts an inventory created by this extractor into a PURL. -func (e Extractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { +// ToPURL converts a package created by this extractor into a PURL. +func (e Extractor) ToPURL(p *extractor.Package) *purl.PackageURL { return &purl.PackageURL{ Type: purl.TypeGeneric, Namespace: "microsoft", - Name: i.Name, - Version: i.Version, + Name: p.Name, + Version: p.Version, } } // Ecosystem returns no ecosystem since OSV does not support windows regpatchlevel yet. -func (Extractor) Ecosystem(i *extractor.Inventory) string { return "" } +func (Extractor) Ecosystem(p *extractor.Package) string { return "" } diff --git a/extractor/standalone/windows/regpatchlevel/regpatchlevel_windows_test.go b/extractor/standalone/windows/regpatchlevel/regpatchlevel_windows_test.go index 1ab8684f..cda83e73 100644 --- a/extractor/standalone/windows/regpatchlevel/regpatchlevel_windows_test.go +++ b/extractor/standalone/windows/regpatchlevel/regpatchlevel_windows_test.go @@ -30,11 +30,11 @@ func TestExtract(t *testing.T) { tests := []struct { name string reg *mockregistry.MockRegistry - want []*extractor.Inventory + want []*extractor.Package wantErr bool }{ { - name: "listOfPackages_returnsInventory", + name: "listOfPackages_returnsPackage", reg: &mockregistry.MockRegistry{ Keys: map[string]registry.Key{ regPackagesRoot: &mockregistry.MockKey{ @@ -60,7 +60,7 @@ func TestExtract(t *testing.T) { }, }, }, - want: []*extractor.Inventory{ + want: []*extractor.Package{ { Name: "Package_for_KB5020683~31bf3856ad364e35~amd64~~19041.2304.1.3", Version: "19041.2304.1.3", diff --git a/internal/guidedremediation/matcher/matcher.go b/internal/guidedremediation/matcher/matcher.go index c9cfad20..b524b64b 100644 --- a/internal/guidedremediation/matcher/matcher.go +++ b/internal/guidedremediation/matcher/matcher.go @@ -27,5 +27,5 @@ import ( // VulnerabilityMatcher interface provides functionality get a list of affecting vulnerabilities for each package in an inventory. type VulnerabilityMatcher interface { - MatchVulnerabilities(ctx context.Context, invs []*extractor.Inventory) ([][]*osvschema.Vulnerability, error) + MatchVulnerabilities(ctx context.Context, pkgs []*extractor.Package) ([][]*osvschema.Vulnerability, error) } diff --git a/internal/guidedremediation/matchertest/mock_vulnerability_matcher.go b/internal/guidedremediation/matchertest/mock_vulnerability_matcher.go index 40cd898c..a7c6eebe 100644 --- a/internal/guidedremediation/matchertest/mock_vulnerability_matcher.go +++ b/internal/guidedremediation/matchertest/mock_vulnerability_matcher.go @@ -29,12 +29,12 @@ import ( // MockVulnerabilityMatcher is a mock vulnerability matcher for testing. type MockVulnerabilityMatcher []*osvschema.Vulnerability -// MatchVulnerabilities returns all vulnerabilities in the mockVulnerabilityMatcher that affect each of the Inventory items. -func (mvc MockVulnerabilityMatcher) MatchVulnerabilities(ctx context.Context, invs []*extractor.Inventory) ([][]*osvschema.Vulnerability, error) { - result := make([][]*osvschema.Vulnerability, len(invs)) - for i, inv := range invs { +// MatchVulnerabilities returns all vulnerabilities in the mockVulnerabilityMatcher that affect each of the Package items. +func (mvc MockVulnerabilityMatcher) MatchVulnerabilities(ctx context.Context, pkgs []*extractor.Package) ([][]*osvschema.Vulnerability, error) { + result := make([][]*osvschema.Vulnerability, len(pkgs)) + for i, pkg := range pkgs { for _, vuln := range mvc { - if vulns.IsAffected(vuln, inv) { + if vulns.IsAffected(vuln, pkg) { result[i] = append(result[i], vuln) } } diff --git a/internal/guidedremediation/remediation/remediation.go b/internal/guidedremediation/remediation/remediation.go index cebb4e22..1fbe680c 100644 --- a/internal/guidedremediation/remediation/remediation.go +++ b/internal/guidedremediation/remediation/remediation.go @@ -87,10 +87,10 @@ func (opts *Options) matchSeverity(v resolution.Vulnerability) bool { // There are no top-level severity, see if there are individual affected[].severity field. severities = []osvschema.Severity{} for _, sg := range v.Subgraphs { - inv := vulns.VKToInventory(sg.Nodes[sg.Dependency].Version) + pkg := vulns.VKToPackage(sg.Nodes[sg.Dependency].Version) // Make and match a dummy OSV record per affected[] entry to determine which applies. for _, affected := range v.OSV.Affected { - if vulns.IsAffected(&osvschema.Vulnerability{Affected: []osvschema.Affected{affected}}, inv) { + if vulns.IsAffected(&osvschema.Vulnerability{Affected: []osvschema.Affected{affected}}, pkg) { severities = append(severities, affected.Severity...) break } diff --git a/internal/guidedremediation/remediation/strategy/override/override.go b/internal/guidedremediation/remediation/strategy/override/override.go index c6c538a5..fd009120 100644 --- a/internal/guidedremediation/remediation/strategy/override/override.go +++ b/internal/guidedremediation/remediation/strategy/override/override.go @@ -164,7 +164,7 @@ func patchVulns(ctx context.Context, cl resolve.Client, vm matcher.Vulnerability // Count the remaining known vulns that affect this version. count := 0 // remaining vulns for _, rv := range vulnerabilities { - if vulns.IsAffected(rv.OSV, vulns.VKToInventory(ver.VersionKey)) { + if vulns.IsAffected(rv.OSV, vulns.VKToPackage(ver.VersionKey)) { count++ } } diff --git a/internal/guidedremediation/resolution/vulnerabilities.go b/internal/guidedremediation/resolution/vulnerabilities.go index beb4362c..7c391749 100644 --- a/internal/guidedremediation/resolution/vulnerabilities.go +++ b/internal/guidedremediation/resolution/vulnerabilities.go @@ -39,7 +39,7 @@ type Vulnerability struct { // FindVulnerabilities scans for vulnerabilities in a resolved graph. // One Vulnerability is created per unique ID, which may affect multiple graph nodes. func FindVulnerabilities(ctx context.Context, cl matcher.VulnerabilityMatcher, m manifest.Manifest, graph *resolve.Graph) ([]Vulnerability, error) { - nodeVulns, err := cl.MatchVulnerabilities(ctx, graphToInventory(graph)) + nodeVulns, err := cl.MatchVulnerabilities(ctx, graphToPackages(graph)) if err != nil { return nil, err } @@ -80,13 +80,13 @@ func FindVulnerabilities(ctx context.Context, cl matcher.VulnerabilityMatcher, m return vulns, nil } -// graphToInventory is a helper function to convert a Graph into an Inventory for use with VulnerabilityMatcher. -func graphToInventory(g *resolve.Graph) []*extractor.Inventory { +// graphToPackages is a helper function to convert a Graph into an Package for use with VulnerabilityMatcher. +func graphToPackages(g *resolve.Graph) []*extractor.Package { // g.Nodes[0] is the root node of the graph that should be excluded. - inv := make([]*extractor.Inventory, len(g.Nodes)-1) + pkgs := make([]*extractor.Package, len(g.Nodes)-1) for i, n := range g.Nodes[1:] { - inv[i] = vulns.VKToInventory(n.Version) + pkgs[i] = vulns.VKToPackage(n.Version) } - return inv + return pkgs } diff --git a/internal/guidedremediation/vulns/vulns.go b/internal/guidedremediation/vulns/vulns.go index 94723038..00e7740a 100644 --- a/internal/guidedremediation/vulns/vulns.go +++ b/internal/guidedremediation/vulns/vulns.go @@ -25,9 +25,9 @@ import ( "github.com/ossf/osv-schema/bindings/go/osvschema" ) -// VKToInventory converts a resolve.VersionKey to an *extractor.Inventory -func VKToInventory(vk resolve.VersionKey) *extractor.Inventory { - return &extractor.Inventory{ +// VKToPackage converts a resolve.VersionKey to an *extractor.Package +func VKToPackage(vk resolve.VersionKey) *extractor.Package { + return &extractor.Package{ Name: vk.Name, Version: vk.Version, Extractor: mockExtractor{}, @@ -35,12 +35,12 @@ func VKToInventory(vk resolve.VersionKey) *extractor.Inventory { } } -// mockExtractor is for VKToInventory to get the ecosystem. +// mockExtractor is for VKToPackage to get the ecosystem. type mockExtractor struct{} -// Ecosystem returns the ecosystem of the inventory. -func (e mockExtractor) Ecosystem(inv *extractor.Inventory) string { - switch inv.Metadata.(resolve.System) { +// Ecosystem returns the ecosystem of the package. +func (e mockExtractor) Ecosystem(pkg *extractor.Package) string { + switch pkg.Metadata.(resolve.System) { case resolve.NPM: return "npm" case resolve.Maven: @@ -53,24 +53,24 @@ func (e mockExtractor) Ecosystem(inv *extractor.Inventory) string { } // Unnecessary methods stubbed out. -func (e mockExtractor) Name() string { return "" } -func (e mockExtractor) Requirements() *plugin.Capabilities { return nil } -func (e mockExtractor) ToPURL(*extractor.Inventory) *purl.PackageURL { return nil } -func (e mockExtractor) Version() int { return 0 } +func (e mockExtractor) Name() string { return "" } +func (e mockExtractor) Requirements() *plugin.Capabilities { return nil } +func (e mockExtractor) ToPURL(*extractor.Package) *purl.PackageURL { return nil } +func (e mockExtractor) Version() int { return 0 } -// IsAffected returns true if the Vulnerability applies to the package version of the Inventory. -func IsAffected(vuln *osvschema.Vulnerability, inv *extractor.Inventory) bool { - resolveSys, ok := inv.Metadata.(resolve.System) +// IsAffected returns true if the Vulnerability applies to the package version of the Package. +func IsAffected(vuln *osvschema.Vulnerability, pkg *extractor.Package) bool { + resolveSys, ok := pkg.Metadata.(resolve.System) if !ok { return false } sys := resolveSys.Semver() for _, affected := range vuln.Affected { - if affected.Package.Ecosystem != inv.Ecosystem() || - affected.Package.Name != inv.Name { + if affected.Package.Ecosystem != pkg.Ecosystem() || + affected.Package.Name != pkg.Name { continue } - if slices.Contains(affected.Versions, inv.Version) { + if slices.Contains(affected.Versions, pkg.Version) { return true } for _, r := range affected.Ranges { @@ -103,7 +103,7 @@ func IsAffected(vuln *osvschema.Vulnerability, inv *extractor.Inventory) bool { // sys.Compare on strings is expensive, should consider precomputing sys.Parse return sys.Compare(aVer, bVer) }) - idx, exact := slices.BinarySearchFunc(events, inv.Version, func(e osvschema.Event, v string) int { + idx, exact := slices.BinarySearchFunc(events, pkg.Version, func(e osvschema.Event, v string) int { eVer := eventVersion(e) if eVer == "0" { return -1 diff --git a/inventoryindex/inventory_index.go b/inventoryindex/inventory_index.go deleted file mode 100644 index 2888a69a..00000000 --- a/inventoryindex/inventory_index.go +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package inventoryindex is a wrapper around the collected inventory, which -// provides methods for fast lookup of identified software. -package inventoryindex - -import ( - "github.com/google/osv-scalibr/extractor" - "github.com/google/osv-scalibr/purl" -) - -// InventoryIndex allows you to query the inventory result. -type InventoryIndex struct { - // Two-dimensional map: package type -> (package name -> Inventory). - invMap map[string]map[string][]*extractor.Inventory -} - -// New creates an InventoryIndex based on the specified extraction results. -func New(inv []*extractor.Inventory) (*InventoryIndex, error) { - invMap := make(map[string]map[string][]*extractor.Inventory) - for _, i := range inv { - p := toPURL(i) - if p == nil { - continue - } - if _, ok := invMap[p.Type]; !ok { - invMap[p.Type] = make(map[string][]*extractor.Inventory) - } - invMap[p.Type][p.Name] = append(invMap[p.Type][p.Name], i) - } - return &InventoryIndex{invMap: invMap}, nil -} - -// GetAll lists all detected software inventory. -func (ix *InventoryIndex) GetAll() []*extractor.Inventory { - result := []*extractor.Inventory{} - for _, m := range ix.invMap { - for _, i := range m { - result = append(result, i...) - } - } - return result -} - -// GetAllOfType lists all detected software inventory of a given purl -// package type (e.g. "deb" "golang" "pypi"). -func (ix *InventoryIndex) GetAllOfType(packageType string) []*extractor.Inventory { - result := []*extractor.Inventory{} - m, ok := ix.invMap[packageType] - if !ok { - return result - } - for _, i := range m { - result = append(result, i...) - } - return result -} - -// GetSpecific lists all versions of a software with the specified name+package type. -func (ix *InventoryIndex) GetSpecific(name string, packageType string) []*extractor.Inventory { - result := []*extractor.Inventory{} - m, ok := ix.invMap[packageType] - if !ok { - return result - } - i, ok := m[name] - if !ok { - return result - } - return i -} - -func toPURL(i *extractor.Inventory) *purl.PackageURL { - return i.Extractor.ToPURL(i) -} diff --git a/packageindex/package_index.go b/packageindex/package_index.go new file mode 100644 index 00000000..cf63edc4 --- /dev/null +++ b/packageindex/package_index.go @@ -0,0 +1,87 @@ +// Copyright 2025 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package packageindex is a wrapper around the collected package, which +// provides methods for fast lookup of identified software. +package packageindex + +import ( + "github.com/google/osv-scalibr/extractor" + "github.com/google/osv-scalibr/purl" +) + +// PackageIndex allows you to query the package result. +type PackageIndex struct { + // Two-dimensional map: package type -> (package name -> Package). + pkgMap map[string]map[string][]*extractor.Package +} + +// New creates a PackageIndex based on the specified extraction results. +func New(pkgs []*extractor.Package) (*PackageIndex, error) { + pkgMap := make(map[string]map[string][]*extractor.Package) + for _, pkg := range pkgs { + p := toPURL(pkg) + if p == nil { + continue + } + if _, ok := pkgMap[p.Type]; !ok { + pkgMap[p.Type] = make(map[string][]*extractor.Package) + } + pkgMap[p.Type][p.Name] = append(pkgMap[p.Type][p.Name], pkg) + } + return &PackageIndex{pkgMap: pkgMap}, nil +} + +// GetAll lists all detected software packages. +func (px *PackageIndex) GetAll() []*extractor.Package { + result := []*extractor.Package{} + for _, m := range px.pkgMap { + for _, p := range m { + result = append(result, p...) + } + } + return result +} + +// GetAllOfType lists all detected software package of a given purl +// package type (e.g. "deb" "golang" "pypi"). +func (px *PackageIndex) GetAllOfType(pkgType string) []*extractor.Package { + result := []*extractor.Package{} + m, ok := px.pkgMap[pkgType] + if !ok { + return result + } + for _, p := range m { + result = append(result, p...) + } + return result +} + +// GetSpecific lists all versions of a software with the specified name+package type. +func (px *PackageIndex) GetSpecific(name string, pkgType string) []*extractor.Package { + result := []*extractor.Package{} + m, ok := px.pkgMap[pkgType] + if !ok { + return result + } + p, ok := m[name] + if !ok { + return result + } + return p +} + +func toPURL(p *extractor.Package) *purl.PackageURL { + return p.Extractor.ToPURL(p) +} diff --git a/inventoryindex/inventory_index_test.go b/packageindex/package_index_test.go similarity index 55% rename from inventoryindex/inventory_index_test.go rename to packageindex/package_index_test.go index 73e85000..538594cc 100644 --- a/inventoryindex/inventory_index_test.go +++ b/packageindex/package_index_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package inventoryindex_test +package packageindex_test import ( "testing" @@ -22,114 +22,114 @@ import ( "github.com/google/osv-scalibr/extractor" "github.com/google/osv-scalibr/extractor/filesystem/language/javascript/packagejson" "github.com/google/osv-scalibr/extractor/filesystem/language/python/wheelegg" - "github.com/google/osv-scalibr/inventoryindex" + "github.com/google/osv-scalibr/packageindex" ) var ( - invLess = func(i1, i2 *extractor.Inventory) bool { + pkgLess = func(i1, i2 *extractor.Package) bool { return i1.Name < i2.Name } - sortInv = cmpopts.SortSlices(invLess) + sortPKGs = cmpopts.SortSlices(pkgLess) allowUnexported = cmp.AllowUnexported(packagejson.Extractor{}, wheelegg.Extractor{}) ) func TestGetAll(t *testing.T) { npmEx := packagejson.New(packagejson.DefaultConfig()) pipEx := wheelegg.New(wheelegg.DefaultConfig()) - inv := []*extractor.Inventory{ + pkgs := []*extractor.Package{ {Name: "software1", Extractor: npmEx}, {Name: "software2", Extractor: pipEx}, {Name: "software3", Extractor: pipEx}, } - want := inv + want := pkgs - ix, err := inventoryindex.New(inv) + px, err := packageindex.New(pkgs) if err != nil { - t.Fatalf("inventoryindex.New(%v): %v", inv, err) + t.Fatalf("packageindex.New(%v): %v", pkgs, err) } - got := ix.GetAll() - if diff := cmp.Diff(want, got, sortInv, allowUnexported); diff != "" { - t.Errorf("inventoryindex.New(%v).GetAll(): unexpected inventory (-want +got):\n%s", inv, diff) + got := px.GetAll() + if diff := cmp.Diff(want, got, sortPKGs, allowUnexported); diff != "" { + t.Errorf("packageindex.New(%v).GetAll(): unexpected package (-want +got):\n%s", pkgs, diff) } } func TestGetAllOfType(t *testing.T) { npmEx := packagejson.New(packagejson.DefaultConfig()) pipEx := wheelegg.New(wheelegg.DefaultConfig()) - inv := []*extractor.Inventory{ + pkgs := []*extractor.Package{ {Name: "software1", Extractor: npmEx}, {Name: "software2", Extractor: pipEx}, {Name: "software3", Extractor: pipEx}, } - want := []*extractor.Inventory{ + want := []*extractor.Package{ {Name: "software2", Extractor: pipEx}, {Name: "software3", Extractor: pipEx}, } - ix, err := inventoryindex.New(inv) + px, err := packageindex.New(pkgs) if err != nil { - t.Fatalf("inventoryindex.New(%v): %v", inv, err) + t.Fatalf("packageindex.New(%v): %v", pkgs, err) } - got := ix.GetAllOfType("pypi") - if diff := cmp.Diff(want, got, sortInv, allowUnexported); diff != "" { - t.Errorf("inventoryindex.New(%v).GetAllOfType(pypi): unexpected inventory (-want +got):\n%s", inv, diff) + got := px.GetAllOfType("pypi") + if diff := cmp.Diff(want, got, sortPKGs, allowUnexported); diff != "" { + t.Errorf("packageindex.New(%v).GetAllOfType(pypi): unexpected package (-want +got):\n%s", pkgs, diff) } } func TestGetSpecific(t *testing.T) { npmEx := packagejson.New(packagejson.DefaultConfig()) pipEx := wheelegg.New(wheelegg.DefaultConfig()) - inv1 := &extractor.Inventory{Name: "software1", Version: "1.2.3", Extractor: npmEx} - inv2 := &extractor.Inventory{Name: "software2", Version: "1.2.3", Extractor: pipEx} - inv3 := &extractor.Inventory{Name: "software3", Extractor: pipEx} - inv4v123 := &extractor.Inventory{Name: "software4", Version: "1.2.3", Extractor: npmEx} - inv4v456 := &extractor.Inventory{Name: "software4", Version: "4.5.6", Extractor: npmEx} - inv := []*extractor.Inventory{inv1, inv2, inv3, inv4v123, inv4v456} + pkg1 := &extractor.Package{Name: "software1", Version: "1.2.3", Extractor: npmEx} + pkg2 := &extractor.Package{Name: "software2", Version: "1.2.3", Extractor: pipEx} + pkg3 := &extractor.Package{Name: "software3", Extractor: pipEx} + pkg4v123 := &extractor.Package{Name: "software4", Version: "1.2.3", Extractor: npmEx} + pkg4v456 := &extractor.Package{Name: "software4", Version: "4.5.6", Extractor: npmEx} + pkgs := []*extractor.Package{pkg1, pkg2, pkg3, pkg4v123, pkg4v456} testCases := []struct { desc string pkgType string pkgName string - want []*extractor.Inventory + want []*extractor.Package }{ { desc: "No version or namespace", pkgType: "pypi", pkgName: "software3", - want: []*extractor.Inventory{inv3}, + want: []*extractor.Package{pkg3}, }, { desc: "software with version", pkgType: "pypi", pkgName: "software2", - want: []*extractor.Inventory{inv2}, + want: []*extractor.Package{pkg2}, }, { desc: "software with namespace", pkgType: "npm", pkgName: "software1", - want: []*extractor.Inventory{inv1}, + want: []*extractor.Package{pkg1}, }, { desc: "multiple versions", pkgType: "npm", pkgName: "software4", - want: []*extractor.Inventory{inv4v123, inv4v456}, + want: []*extractor.Package{pkg4v123, pkg4v456}, }, } for _, tc := range testCases { t.Run(tc.desc, func(t *testing.T) { - ix, err := inventoryindex.New(inv) + px, err := packageindex.New(pkgs) if err != nil { - t.Fatalf("inventoryindex.New(%v): %v", inv, err) + t.Fatalf("packageindex.New(%v): %v", pkgs, err) } - got := ix.GetSpecific(tc.pkgName, tc.pkgType) - if diff := cmp.Diff(tc.want, got, sortInv, allowUnexported); diff != "" { - t.Errorf("inventoryindex.New(%v).GetSpecific(%s, %s): unexpected inventory (-want +got):\n%s", inv, tc.pkgName, tc.pkgType, diff) + got := px.GetSpecific(tc.pkgName, tc.pkgType) + if diff := cmp.Diff(tc.want, got, sortPKGs, allowUnexported); diff != "" { + t.Errorf("packageindex.New(%v).GetSpecific(%s, %s): unexpected package (-want +got):\n%s", pkgs, tc.pkgName, tc.pkgType, diff) } }) } diff --git a/plugin/plugin.go b/plugin/plugin.go index b4d1b6c5..0e4420a8 100644 --- a/plugin/plugin.go +++ b/plugin/plugin.go @@ -79,7 +79,7 @@ type Plugin interface { // LINT.IfChange -// Status contains the status and version of the inventory+vuln plugins that ran. +// Status contains the status and version of the plugins that ran. type Status struct { Name string Version int diff --git a/scalibr.go b/scalibr.go index 19c8830e..0dde6293 100644 --- a/scalibr.go +++ b/scalibr.go @@ -33,8 +33,8 @@ import ( "github.com/google/osv-scalibr/extractor" "github.com/google/osv-scalibr/extractor/filesystem" "github.com/google/osv-scalibr/extractor/standalone" - "github.com/google/osv-scalibr/inventoryindex" "github.com/google/osv-scalibr/log" + "github.com/google/osv-scalibr/packageindex" "github.com/google/osv-scalibr/plugin" "github.com/google/osv-scalibr/stats" @@ -68,7 +68,7 @@ type ScanConfig struct { // Example use case: Scanning a container image or source code repo that is // mounted to a local dir. ScanRoots []*scalibrfs.ScanRoot - // Optional: Individual files to extract inventory from. If specified, the + // Optional: Individual files to extract package from. If specified, the // extractors will only look at these files during the filesystem traversal. // Note that on real filesystems these are not relative to the ScanRoots and // thus need to be in sub-directories of one of the ScanRoots. @@ -88,7 +88,7 @@ type ScanConfig struct { ReadSymlinks bool // Optional: Limit for visited inodes. If 0, no limit is applied. MaxInodes int - // Optional: By default, inventories stores a path relative to the scan root. If StoreAbsolutePath + // Optional: By default, inventory paths are relative to the scan root. If StoreAbsolutePath // is set, the absolute path is stored instead. StoreAbsolutePath bool // Optional: If true, print a detailed analysis of the duration of each extractor. @@ -153,17 +153,23 @@ func (cfg *ScanConfig) ValidatePluginRequirements() error { // LINT.IfChange -// ScanResult stores the software inventory and security findings that a scan run found. +// ScanResult stores the results of a scan incl. scan status and artifacts found. type ScanResult struct { Version string StartTime time.Time EndTime time.Time // Status of the overall scan. Status *plugin.ScanStatus - // Status and versions of the inventory+vuln plugins that ran. + // Status and versions of the plugins that ran. PluginStatus []*plugin.Status - Inventories []*extractor.Inventory - Findings []*detector.Finding + Inventory *Inventory +} + +// Inventory stores the artifacts (e.g. software packages, security findings) +// that a scan found. +type Inventory struct { + Packages []*extractor.Package + Findings []*detector.Finding } // LINT.ThenChange(/binary/proto/scan_result.proto) @@ -177,9 +183,8 @@ func (Scanner) Scan(ctx context.Context, config *ScanConfig) (sr *ScanResult) { config.Stats.AfterScan(time.Since(sr.StartTime), sr.Status) }() sro := &newScanResultOptions{ - StartTime: time.Now(), - Inventories: []*extractor.Inventory{}, - Findings: []*detector.Finding{}, + StartTime: time.Now(), + Inventory: &Inventory{}, } if err := config.EnableRequiredExtractors(); err != nil { sro.Err = err @@ -208,31 +213,31 @@ func (Scanner) Scan(ctx context.Context, config *ScanConfig) (sr *ScanResult) { PrintDurationAnalysis: config.PrintDurationAnalysis, ErrorOnFSErrors: config.ErrorOnFSErrors, } - inventories, extractorStatus, err := filesystem.Run(ctx, extractorConfig) + packages, extractorStatus, err := filesystem.Run(ctx, extractorConfig) if err != nil { sro.Err = err sro.EndTime = time.Now() return newScanResult(sro) } - sro.Inventories = inventories + sro.Inventory.Packages = packages sro.ExtractorStatus = extractorStatus sysroot := config.ScanRoots[0] standaloneCfg := &standalone.Config{ Extractors: config.StandaloneExtractors, ScanRoot: &scalibrfs.ScanRoot{FS: sysroot.FS, Path: sysroot.Path}, } - standaloneInv, standaloneStatus, err := standalone.Run(ctx, standaloneCfg) + standalonePKGs, standaloneStatus, err := standalone.Run(ctx, standaloneCfg) if err != nil { sro.Err = err sro.EndTime = time.Now() return newScanResult(sro) } - sro.Inventories = append(sro.Inventories, standaloneInv...) + sro.Inventory.Packages = append(sro.Inventory.Packages, standalonePKGs...) sro.ExtractorStatus = append(sro.ExtractorStatus, standaloneStatus...) - ix, err := inventoryindex.New(sro.Inventories) + px, err := packageindex.New(sro.Inventory.Packages) if err != nil { sro.Err = err sro.EndTime = time.Now() @@ -240,9 +245,9 @@ func (Scanner) Scan(ctx context.Context, config *ScanConfig) (sr *ScanResult) { } findings, detectorStatus, err := detector.Run( - ctx, config.Stats, config.Detectors, &scalibrfs.ScanRoot{FS: sysroot.FS, Path: sysroot.Path}, ix, + ctx, config.Stats, config.Detectors, &scalibrfs.ScanRoot{FS: sysroot.FS, Path: sysroot.Path}, px, ) - sro.Findings = findings + sro.Inventory.Findings = findings sro.DetectorStatus = detectorStatus if err != nil { sro.Err = err @@ -252,8 +257,8 @@ func (Scanner) Scan(ctx context.Context, config *ScanConfig) (sr *ScanResult) { return newScanResult(sro) } -// ScanContainer scans the provided container image for inventory and security findings using the -// provided scan config. It populates the LayerDetails field of the inventory with the origin layer +// ScanContainer scans the provided container image for package and security findings using the +// provided scan config. It populates the LayerDetails field of the package with the origin layer // details. Functions to create an Image from a tarball, remote name, or v1.Image are available in // the artifact/image/layerscanning/image package. func (s Scanner) ScanContainer(ctx context.Context, img *image.Image, config *ScanConfig) (sr *ScanResult, err error) { @@ -280,7 +285,7 @@ func (s Scanner) ScanContainer(ctx context.Context, img *image.Image, config *Sc } scanResult := s.Scan(ctx, config) - inventory := scanResult.Inventories + pkg := scanResult.Inventory.Packages extractorConfig := &filesystem.Config{ Stats: config.Stats, ReadSymlinks: config.ReadSymlinks, @@ -295,8 +300,8 @@ func (s Scanner) ScanContainer(ctx context.Context, img *image.Image, config *Sc PrintDurationAnalysis: config.PrintDurationAnalysis, } - // Populate the LayerDetails field of the inventory by tracing the layer origins. - trace.PopulateLayerDetails(ctx, inventory, chainLayers, extractorConfig) + // Populate the LayerDetails field of the package by tracing the layer origins. + trace.PopulateLayerDetails(ctx, pkg, chainLayers, extractorConfig) return scanResult, nil } @@ -304,9 +309,8 @@ type newScanResultOptions struct { StartTime time.Time EndTime time.Time ExtractorStatus []*plugin.Status - Inventories []*extractor.Inventory DetectorStatus []*plugin.Status - Findings []*detector.Finding + Inventory *Inventory Err error } @@ -323,8 +327,7 @@ func newScanResult(o *newScanResultOptions) *ScanResult { EndTime: o.EndTime, Status: status, PluginStatus: append(o.ExtractorStatus, o.DetectorStatus...), - Inventories: o.Inventories, - Findings: o.Findings, + Inventory: o.Inventory, } // Sort results for better diffing. @@ -343,17 +346,17 @@ func hasFailedPlugins(statuses []*plugin.Status) bool { // sortResults sorts the result to make the output deterministic and diffable. func sortResults(results *ScanResult) { - for _, inventory := range results.Inventories { - sort.Strings(inventory.Locations) + for _, pkg := range results.Inventory.Packages { + sort.Strings(pkg.Locations) } slices.SortFunc(results.PluginStatus, cmpStatus) - slices.SortFunc(results.Inventories, CmpInventories) - slices.SortFunc(results.Findings, cmpFindings) + slices.SortFunc(results.Inventory.Packages, CmpPackages) + slices.SortFunc(results.Inventory.Findings, cmpFindings) } -// CmpInventories is a comparison helper fun to be used for sorting Inventory structs. -func CmpInventories(a, b *extractor.Inventory) int { +// CmpPackages is a comparison helper fun to be used for sorting Package structs. +func CmpPackages(a, b *extractor.Package) int { res := cmp.Or( cmp.Compare(a.Name, b.Name), cmp.Compare(a.Version, b.Version), diff --git a/scalibr_test.go b/scalibr_test.go index c6718c16..76ff2a79 100644 --- a/scalibr_test.go +++ b/scalibr_test.go @@ -30,7 +30,7 @@ import ( "github.com/google/osv-scalibr/extractor" "github.com/google/osv-scalibr/extractor/filesystem" scalibrfs "github.com/google/osv-scalibr/fs" - "github.com/google/osv-scalibr/inventoryindex" + "github.com/google/osv-scalibr/packageindex" "github.com/google/osv-scalibr/plugin" "github.com/google/osv-scalibr/purl" fd "github.com/google/osv-scalibr/testing/fakedetector" @@ -53,13 +53,13 @@ func TestScan(t *testing.T) { tmpRoot := []*scalibrfs.ScanRoot{{FS: scalibrfs.DirFS(tmp), Path: tmp}} os.WriteFile(filepath.Join(tmp, "file.txt"), []byte("Content"), 0644) - invName := "software" + pkgName := "software" fakeExtractor := fe.New( "python/wheelegg", 1, []string{"file.txt"}, - map[string]fe.NamesErr{"file.txt": {Names: []string{invName}, Err: nil}}, + map[string]fe.NamesErr{"file.txt": {Names: []string{pkgName}, Err: nil}}, ) - inventory := &extractor.Inventory{ - Name: invName, + pkg := &extractor.Package{ + Name: pkgName, Locations: []string{"file.txt"}, Extractor: fakeExtractor, } @@ -85,8 +85,10 @@ func TestScan(t *testing.T) { {Name: "detector", Version: 2, Status: success}, {Name: "python/wheelegg", Version: 1, Status: success}, }, - Inventories: []*extractor.Inventory{inventory}, - Findings: []*detector.Finding{withDetectorName(finding, "detector")}, + Inventory: &scalibr.Inventory{ + Packages: []*extractor.Package{pkg}, + Findings: []*detector.Finding{withDetectorName(finding, "detector")}, + }, }, }, { @@ -110,8 +112,10 @@ func TestScan(t *testing.T) { {Name: "detector", Version: 2, Status: success}, {Name: "detector", Version: 3, Status: success}, }, - Inventories: []*extractor.Inventory{}, - Findings: []*detector.Finding{}, + Inventory: &scalibr.Inventory{ + Packages: []*extractor.Package{}, + Findings: []*detector.Finding{}, + }, }, }, { @@ -129,8 +133,10 @@ func TestScan(t *testing.T) { {Name: "detector", Version: 2, Status: success}, {Name: "python/wheelegg", Version: 1, Status: extFailure}, }, - Inventories: nil, - Findings: []*detector.Finding{withDetectorName(finding, "detector")}, + Inventory: &scalibr.Inventory{ + Packages: nil, + Findings: []*detector.Finding{withDetectorName(finding, "detector")}, + }, }, }, { @@ -148,8 +154,10 @@ func TestScan(t *testing.T) { {Name: "detector", Version: 2, Status: detFailure}, {Name: "python/wheelegg", Version: 1, Status: success}, }, - Inventories: []*extractor.Inventory{inventory}, - Findings: []*detector.Finding{}, + Inventory: &scalibr.Inventory{ + Packages: []*extractor.Package{pkg}, + Findings: []*detector.Finding{}, + }, }, }, { @@ -163,8 +171,7 @@ func TestScan(t *testing.T) { Status: plugin.ScanStatusFailed, FailureReason: "no scan root specified", }, - Inventories: []*extractor.Inventory{}, - Findings: []*detector.Finding{}, + Inventory: &scalibr.Inventory{}, }, }, } @@ -272,11 +279,11 @@ type fakeExNeedsNetwork struct { func (fakeExNeedsNetwork) Name() string { return "fake-extractor" } func (fakeExNeedsNetwork) Version() int { return 0 } func (fakeExNeedsNetwork) FileRequired(_ filesystem.FileAPI) bool { return false } -func (fakeExNeedsNetwork) Extract(ctx context.Context, input *filesystem.ScanInput) (inventory []*extractor.Inventory, err error) { +func (fakeExNeedsNetwork) Extract(ctx context.Context, input *filesystem.ScanInput) (pkg []*extractor.Package, err error) { return nil, nil } -func (e fakeExNeedsNetwork) ToPURL(i *extractor.Inventory) *purl.PackageURL { return nil } -func (e fakeExNeedsNetwork) Ecosystem(i *extractor.Inventory) string { return "" } +func (e fakeExNeedsNetwork) ToPURL(p *extractor.Package) *purl.PackageURL { return nil } +func (e fakeExNeedsNetwork) Ecosystem(p *extractor.Package) string { return "" } func (fakeExNeedsNetwork) Requirements() *plugin.Capabilities { return &plugin.Capabilities{Network: plugin.NetworkOnline} @@ -288,7 +295,7 @@ type fakeDetNeedsFS struct { func (fakeDetNeedsFS) Name() string { return "fake-extractor" } func (fakeDetNeedsFS) Version() int { return 0 } func (fakeDetNeedsFS) RequiredExtractors() []string { return nil } -func (fakeDetNeedsFS) Scan(ctx context.Context, scanRoot *scalibrfs.ScanRoot, ix *inventoryindex.InventoryIndex) ([]*detector.Finding, error) { +func (fakeDetNeedsFS) Scan(ctx context.Context, scanRoot *scalibrfs.ScanRoot, px *packageindex.PackageIndex) ([]*detector.Finding, error) { return nil, nil } func (fakeDetNeedsFS) Requirements() *plugin.Capabilities { diff --git a/testing/extracttest/compare.go b/testing/extracttest/compare.go index 318094de..8769a11d 100644 --- a/testing/extracttest/compare.go +++ b/testing/extracttest/compare.go @@ -21,10 +21,10 @@ import ( "github.com/google/osv-scalibr/extractor" ) -// InventoryCmpLess is a comparator function for Inventories, to be used in -// tests with cmp.Diff to disregard the order in which the Inventories +// PackageCmpLess is a comparator function for Packages, to be used in +// tests with cmp.Diff to disregard the order in which the Packages // are reported. -func InventoryCmpLess(a, b *extractor.Inventory) bool { +func PackageCmpLess(a, b *extractor.Package) bool { aLoc := fmt.Sprintf("%v", a.Locations) bLoc := fmt.Sprintf("%v", b.Locations) diff --git a/testing/extracttest/compare_test.go b/testing/extracttest/compare_test.go index a76e783f..f2a46207 100644 --- a/testing/extracttest/compare_test.go +++ b/testing/extracttest/compare_test.go @@ -20,10 +20,10 @@ import ( "github.com/google/osv-scalibr/extractor" ) -func TestInventoryCmpLess(t *testing.T) { +func TestPackageCmpLess(t *testing.T) { type args struct { - a *extractor.Inventory - b *extractor.Inventory + a *extractor.Package + b *extractor.Package } tests := []struct { name string @@ -33,12 +33,12 @@ func TestInventoryCmpLess(t *testing.T) { { name: "Location difference", args: args{ - a: &extractor.Inventory{ + a: &extractor.Package{ Name: "a", Version: "2.0.0", Locations: []string{"aaa/bbb"}, }, - b: &extractor.Inventory{ + b: &extractor.Package{ Name: "a", Version: "1.0.0", Locations: []string{"ccc/ddd"}, @@ -49,12 +49,12 @@ func TestInventoryCmpLess(t *testing.T) { { name: "Version difference", args: args{ - a: &extractor.Inventory{ + a: &extractor.Package{ Name: "a", Version: "2.0.0", Locations: []string{"aaa/bbb"}, }, - b: &extractor.Inventory{ + b: &extractor.Package{ Name: "a", Version: "1.0.0", Locations: []string{"aaa/bbb"}, @@ -65,8 +65,8 @@ func TestInventoryCmpLess(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got := InventoryCmpLess(tt.args.a, tt.args.b); got != tt.want { - t.Errorf("InventoryCmpLess() = %v, want %v", got, tt.want) + if got := PackageCmpLess(tt.args.a, tt.args.b); got != tt.want { + t.Errorf("PackageCmpLess() = %v, want %v", got, tt.want) } }) } diff --git a/testing/extracttest/mockscaninput.go b/testing/extracttest/mockscaninput.go index 0e8bac93..0d35ff33 100644 --- a/testing/extracttest/mockscaninput.go +++ b/testing/extracttest/mockscaninput.go @@ -39,10 +39,10 @@ type ScanInputMockConfig struct { // TestTableEntry is a entry to pass to ExtractionTester type TestTableEntry struct { - Name string - InputConfig ScanInputMockConfig - WantInventory []*extractor.Inventory - WantErr error + Name string + InputConfig ScanInputMockConfig + WantPackages []*extractor.Package + WantErr error } // CloseTestScanInput takes a scan input generated by GenerateScanInputMock diff --git a/testing/fakedetector/fake_detector.go b/testing/fakedetector/fake_detector.go index 35b8f6fa..83fcff14 100644 --- a/testing/fakedetector/fake_detector.go +++ b/testing/fakedetector/fake_detector.go @@ -20,7 +20,7 @@ import ( "github.com/google/osv-scalibr/detector" scalibrfs "github.com/google/osv-scalibr/fs" - "github.com/google/osv-scalibr/inventoryindex" + "github.com/google/osv-scalibr/packageindex" "github.com/google/osv-scalibr/plugin" ) @@ -64,7 +64,7 @@ func (d *fakeDetector) Requirements() *plugin.Capabilities { return &plugin.Capa func (d *fakeDetector) RequiredExtractors() []string { return d.ReqExtractors } // Scan always returns the same predefined finding or error. -func (d *fakeDetector) Scan(ctx context.Context, scanRoot *scalibrfs.ScanRoot, ix *inventoryindex.InventoryIndex) ([]*detector.Finding, error) { +func (d *fakeDetector) Scan(ctx context.Context, scanRoot *scalibrfs.ScanRoot, px *packageindex.PackageIndex) ([]*detector.Finding, error) { if d.Finding == nil { return nil, d.Err } diff --git a/testing/fakeextractor/fake_extractor.go b/testing/fakeextractor/fake_extractor.go index c6f2ff6d..0db395d8 100644 --- a/testing/fakeextractor/fake_extractor.go +++ b/testing/fakeextractor/fake_extractor.go @@ -27,7 +27,7 @@ import ( "github.com/google/osv-scalibr/purl" ) -// NamesErr is a list of Inventory names and an error. +// NamesErr is a list of Package names and an error. type NamesErr struct { Names []string Err error @@ -48,7 +48,7 @@ var AllowUnexported = cmp.AllowUnexported(fakeExtractor{}) // New returns a fake fakeExtractor. // // The fakeExtractor returns FileRequired(path) = true for any path in requiredFiles. -// The fakeExtractor returns the inventory and error from pathToNamesErr given the same path to Extract(...). +// The fakeExtractor returns the package and error from pathToNamesErr given the same path to Extract(...). func New(name string, version int, requiredFiles []string, pathToNamesErr map[string]NamesErr) filesystem.Extractor { rfs := map[string]bool{} for _, path := range requiredFiles { @@ -87,39 +87,39 @@ func (e *fakeExtractor) FileRequired(api filesystem.FileAPI) bool { return e.requiredFiles[filepath.ToSlash(api.Path())] } -// Extract extracts inventory data relevant for the extractor from a given file. +// Extract extracts package data relevant for the extractor from a given file. // -// Extract returns the inventory list and error associated with input.Path from the pathToInventoryErr map used -// during construction in NewExtractor(..., pathToInventoryErr, ...). +// Extract returns the package list and error associated with input.Path from the pathToPackageErr map used +// during construction in NewExtractor(..., pathToPackageErr, ...). // Note: because mapfs forces all paths to slash, we have to align with it here. -func (e *fakeExtractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { +func (e *fakeExtractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Package, error) { path := filepath.ToSlash(input.Path) namesErr, ok := e.pathToNamesErr[path] if !ok { return nil, errors.New("unrecognized path") } - invs := []*extractor.Inventory{} + pkgs := []*extractor.Package{} for _, name := range namesErr.Names { - invs = append(invs, &extractor.Inventory{ + pkgs = append(pkgs, &extractor.Package{ Name: name, Locations: []string{path}, }) } - return invs, namesErr.Err + return pkgs, namesErr.Err } -// ToPURL returns a fake PURL based on the inventory name+version. -func (e *fakeExtractor) ToPURL(i *extractor.Inventory) *purl.PackageURL { +// ToPURL returns a fake PURL based on the package name+version. +func (e *fakeExtractor) ToPURL(p *extractor.Package) *purl.PackageURL { return &purl.PackageURL{ Type: purl.TypePyPi, - Name: i.Name, - Version: i.Version, + Name: p.Name, + Version: p.Version, } } // Ecosystem returns a fake ecosystem. -func (e *fakeExtractor) Ecosystem(i *extractor.Inventory) string { +func (e *fakeExtractor) Ecosystem(p *extractor.Package) string { return "FakeEcosystem" } diff --git a/testing/fakeextractor/fake_extractor_test.go b/testing/fakeextractor/fake_extractor_test.go index 88f629e7..847b2ee3 100644 --- a/testing/fakeextractor/fake_extractor_test.go +++ b/testing/fakeextractor/fake_extractor_test.go @@ -133,7 +133,7 @@ func TestFileRequired(t *testing.T) { func TestExtract(t *testing.T) { name1 := "package" name2 := "another package" - multipleInventories := []*extractor.Inventory{{ + multiplePackages := []*extractor.Package{{ Name: name1, Locations: []string{"some path"}, }, { @@ -150,7 +150,7 @@ func TestExtract(t *testing.T) { name string extractor filesystem.Extractor args args - want []*extractor.Inventory + want []*extractor.Package wantErr error }{ { @@ -159,7 +159,7 @@ func TestExtract(t *testing.T) { "some path": {nil, nil}, }), args: args{context.Background(), &filesystem.ScanInput{Path: "some path"}}, - want: []*extractor.Inventory{}, + want: []*extractor.Package{}, }, { name: "multiple results", @@ -167,7 +167,7 @@ func TestExtract(t *testing.T) { "some path": {[]string{name1, name2}, nil}, }), args: args{context.Background(), &filesystem.ScanInput{Path: "some path"}}, - want: multipleInventories, + want: multiplePackages, }, { name: "unrecognized path throws an error",