-
Notifications
You must be signed in to change notification settings - Fork 823
feat: populate package architecture for matching #3504
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
eb6225a
f87eccc
9f7b6e9
012eb44
b70b46f
b1c4aed
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| package v6 | ||
|
|
||
| import ( | ||
| "fmt" | ||
|
|
||
| "gorm.io/gorm" | ||
| ) | ||
|
|
||
| type ArchitectureAliasStoreReader interface { | ||
| // GetArchitectureAliases returns the architecture alias table (alias spelling -> canonical | ||
| // token), used by the architecture qualifier to fold dialect spellings at match time. | ||
| GetArchitectureAliases() (map[string]string, error) | ||
| } | ||
|
|
||
| type architectureAliasStore struct { | ||
| db *gorm.DB | ||
| } | ||
|
|
||
| func newArchitectureAliasStore(db *gorm.DB) *architectureAliasStore { | ||
| return &architectureAliasStore{db: db} | ||
| } | ||
|
|
||
| // GetArchitectureAliases returns the architecture alias table as a map of alias spelling to | ||
| // canonical token. A database built before this table existed has no such table; that is not | ||
| // an error — an empty map is returned, which the architecture qualifier reads as "fall back to | ||
| // the built-in default aliases". | ||
| func (s *architectureAliasStore) GetArchitectureAliases() (map[string]string, error) { | ||
| if !s.db.Migrator().HasTable(&ArchitectureAlias{}) { | ||
| return map[string]string{}, nil | ||
| } | ||
|
|
||
| var rows []ArchitectureAlias | ||
| if err := s.db.Find(&rows).Error; err != nil { | ||
| return nil, fmt.Errorf("unable to read architecture aliases: %w", err) | ||
| } | ||
|
|
||
| out := make(map[string]string, len(rows)) | ||
| for _, r := range rows { | ||
| out[r.Alias] = r.Canonical | ||
| } | ||
| return out, nil | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| package v6 | ||
|
|
||
| import ( | ||
| "testing" | ||
|
|
||
| "github.com/stretchr/testify/require" | ||
|
|
||
| "github.com/anchore/grype/grype/pkg/qualifier/architecture" | ||
| ) | ||
|
|
||
| func TestArchitectureAliasStore_GetArchitectureAliases_SeededDefaults(t *testing.T) { | ||
| // setupTestStore opens an empty+writable DB, which seeds InitialData (including the | ||
| // architecture aliases). The read-back must equal the build-time default table. | ||
| s := setupTestStore(t) | ||
|
|
||
| got, err := s.GetArchitectureAliases() | ||
| require.NoError(t, err) | ||
| require.Equal(t, architecture.DefaultAliases(), got) | ||
| } | ||
|
|
||
| func TestArchitectureAliasStore_GetArchitectureAliases_MissingTableIsEmptyNotError(t *testing.T) { | ||
| // a database built before the architecture_aliases table existed has no such table; that | ||
| // must read as an empty map (the qualifier's signal to fall back to built-in defaults), | ||
| // never an error. | ||
| s := setupTestStore(t) | ||
| require.NoError(t, s.db.Migrator().DropTable(&ArchitectureAlias{})) | ||
|
|
||
| got, err := s.GetArchitectureAliases() | ||
| require.NoError(t, err) | ||
| require.Empty(t, got) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -52,6 +52,7 @@ func Models() []any { | |
| &OperatingSystemSpecifierOverride{}, | ||
| &Package{}, | ||
| &PackageSpecifierOverride{}, | ||
| &ArchitectureAlias{}, | ||
|
|
||
| // CPE related search tables | ||
| &AffectedCPEHandle{}, // join on CPE | ||
|
|
@@ -533,6 +534,22 @@ type PackageSpecifierOverride struct { | |
| ReplacementEcosystem *string `gorm:"column:replacement_ecosystem;primaryKey"` | ||
| } | ||
|
|
||
| // ArchitectureAlias folds an architecture spelling onto a canonical token shared by every | ||
| // dialect spelling of the same CPU architecture (e.g. rpm "x86_64" and deb/OCI "amd64" both | ||
| // fold to "amd64"). The architecture qualifier reads this table at match time so cross-dialect | ||
| // arch comparisons don't drop real matches; the data lives in the DB rather than the grype | ||
| // binary so the folding can change without a release. See pkg/qualifier/architecture. | ||
| type ArchitectureAlias struct { | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this complete? Do we need an "is platform independent" bool column or something? Right now the source code knows that We think that this case be added later if need be, and that it is probably not necessary. |
||
| // Alias is an architecture spelling as it may appear on a package or vulnerability entry | ||
| // (e.g. "x86_64"). Only non-canonical spellings are stored; a canonical token resolves to | ||
| // itself by absence. | ||
| Alias string `gorm:"column:alias;primaryKey"` | ||
|
|
||
| // Canonical is the token Alias folds to (e.g. "amd64"). The choice of token is arbitrary; | ||
| // only equivalence across spellings matters. | ||
| Canonical string `gorm:"column:canonical;not null"` | ||
| } | ||
|
|
||
| // OperatingSystem represents a specific release of an operating system. The resolution of the version is | ||
| // relative to the available data by the vulnerability data provider, so though there may be major.minor.patch OS | ||
| // releases, there may only be data available for major.minor. | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This already shipped as a string, but maybe missed opportunity to do a
Set[string]so that we could check "intersection of package arch with vuln arch is not empty" instead of equality.