mirror of
https://github.com/anchore/syft.git
synced 2026-10-11 21:57:22 +02:00
chore(deps): update Go version (#4773)
Signed-off-by: anchore-oss-update-bot <anchore-oss-update-bot@users.noreply.github.com> Co-authored-by: anchore-oss-update-bot <anchore-oss-update-bot@users.noreply.github.com>
This commit is contained in:
co-authored by
anchore-oss-update-bot
parent
26e87c7cd3
commit
5b58ec96b7
@@ -5,8 +5,8 @@ import "reflect"
|
||||
// EvaluateCapabilities evaluates a capability set against a given configuration
|
||||
// and returns the effective capability values as a flat map.
|
||||
// Example: {"license": false, "dependency.depth": ["direct", "indirect"]}
|
||||
func EvaluateCapabilities(caps CapabilitySet, config map[string]interface{}) map[string]interface{} {
|
||||
result := make(map[string]interface{})
|
||||
func EvaluateCapabilities(caps CapabilitySet, config map[string]any) map[string]any {
|
||||
result := make(map[string]any)
|
||||
for _, capField := range caps {
|
||||
result[capField.Name] = EvaluateField(capField, config)
|
||||
}
|
||||
@@ -16,7 +16,7 @@ func EvaluateCapabilities(caps CapabilitySet, config map[string]interface{}) map
|
||||
// EvaluateField evaluates a single capability field against a configuration.
|
||||
// Conditions are evaluated in order, and the first matching condition's value is returned.
|
||||
// If no conditions match, the default value is returned.
|
||||
func EvaluateField(capField CapabilityField, config map[string]interface{}) interface{} {
|
||||
func EvaluateField(capField CapabilityField, config map[string]any) any {
|
||||
// check conditions in order (first match wins)
|
||||
for _, cond := range capField.Conditions {
|
||||
if ConditionMatches(cond.When, config) {
|
||||
@@ -30,7 +30,7 @@ func EvaluateField(capField CapabilityField, config map[string]interface{}) inte
|
||||
// ConditionMatches checks if a condition's when clause matches the given configuration.
|
||||
// All fields in the when clause must match the config (AND logic).
|
||||
// Returns true if all key-value pairs in when match the config.
|
||||
func ConditionMatches(when map[string]interface{}, config map[string]interface{}) bool {
|
||||
func ConditionMatches(when map[string]any, config map[string]any) bool {
|
||||
// all fields in when must match config (AND logic)
|
||||
for key, expectedValue := range when {
|
||||
actualValue, exists := config[key]
|
||||
@@ -46,7 +46,7 @@ func ConditionMatches(when map[string]interface{}, config map[string]interface{}
|
||||
|
||||
// valuesEqual compares two values for equality, handling different types appropriately.
|
||||
// Uses reflect.DeepEqual for complex types like slices and maps.
|
||||
func valuesEqual(a, b interface{}) bool {
|
||||
func valuesEqual(a, b any) bool {
|
||||
// handle nil cases
|
||||
if a == nil && b == nil {
|
||||
return true
|
||||
|
||||
@@ -10,8 +10,8 @@ import (
|
||||
func Test_valuesEqual(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
a interface{}
|
||||
b interface{}
|
||||
a any
|
||||
b any
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
@@ -123,47 +123,47 @@ func Test_valuesEqual(t *testing.T) {
|
||||
func TestConditionMatches(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
when map[string]interface{}
|
||||
config map[string]interface{}
|
||||
when map[string]any
|
||||
config map[string]any
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
name: "empty when clause matches anything",
|
||||
when: map[string]interface{}{},
|
||||
config: map[string]interface{}{"key": "value"},
|
||||
when: map[string]any{},
|
||||
config: map[string]any{"key": "value"},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "empty when clause with empty config",
|
||||
when: map[string]interface{}{},
|
||||
config: map[string]interface{}{},
|
||||
when: map[string]any{},
|
||||
config: map[string]any{},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "single key match",
|
||||
when: map[string]interface{}{"SearchLocalModCacheLicenses": true},
|
||||
config: map[string]interface{}{"SearchLocalModCacheLicenses": true},
|
||||
when: map[string]any{"SearchLocalModCacheLicenses": true},
|
||||
config: map[string]any{"SearchLocalModCacheLicenses": true},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "single key mismatch",
|
||||
when: map[string]interface{}{"SearchLocalModCacheLicenses": true},
|
||||
config: map[string]interface{}{"SearchLocalModCacheLicenses": false},
|
||||
when: map[string]any{"SearchLocalModCacheLicenses": true},
|
||||
config: map[string]any{"SearchLocalModCacheLicenses": false},
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "key missing from config",
|
||||
when: map[string]interface{}{"SearchLocalModCacheLicenses": true},
|
||||
config: map[string]interface{}{},
|
||||
when: map[string]any{"SearchLocalModCacheLicenses": true},
|
||||
config: map[string]any{},
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "multiple keys all match",
|
||||
when: map[string]interface{}{
|
||||
when: map[string]any{
|
||||
"SearchLocalModCacheLicenses": true,
|
||||
"UseNetwork": true,
|
||||
},
|
||||
config: map[string]interface{}{
|
||||
config: map[string]any{
|
||||
"SearchLocalModCacheLicenses": true,
|
||||
"UseNetwork": true,
|
||||
"ExtraKey": "ignored",
|
||||
@@ -172,11 +172,11 @@ func TestConditionMatches(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "multiple keys one mismatch",
|
||||
when: map[string]interface{}{
|
||||
when: map[string]any{
|
||||
"SearchLocalModCacheLicenses": true,
|
||||
"UseNetwork": true,
|
||||
},
|
||||
config: map[string]interface{}{
|
||||
config: map[string]any{
|
||||
"SearchLocalModCacheLicenses": true,
|
||||
"UseNetwork": false,
|
||||
},
|
||||
@@ -184,31 +184,31 @@ func TestConditionMatches(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "multiple keys one missing",
|
||||
when: map[string]interface{}{
|
||||
when: map[string]any{
|
||||
"SearchLocalModCacheLicenses": true,
|
||||
"UseNetwork": true,
|
||||
},
|
||||
config: map[string]interface{}{
|
||||
config: map[string]any{
|
||||
"SearchLocalModCacheLicenses": true,
|
||||
},
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "string value match",
|
||||
when: map[string]interface{}{"mode": "fast"},
|
||||
config: map[string]interface{}{"mode": "fast"},
|
||||
when: map[string]any{"mode": "fast"},
|
||||
config: map[string]any{"mode": "fast"},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "slice value match",
|
||||
when: map[string]interface{}{"formats": []string{"json", "yaml"}},
|
||||
config: map[string]interface{}{"formats": []string{"json", "yaml"}},
|
||||
when: map[string]any{"formats": []string{"json", "yaml"}},
|
||||
config: map[string]any{"formats": []string{"json", "yaml"}},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "slice value mismatch",
|
||||
when: map[string]interface{}{"formats": []string{"json", "yaml"}},
|
||||
config: map[string]interface{}{"formats": []string{"json", "xml"}},
|
||||
when: map[string]any{"formats": []string{"json", "yaml"}},
|
||||
config: map[string]any{"formats": []string{"json", "xml"}},
|
||||
want: false,
|
||||
},
|
||||
}
|
||||
@@ -225,8 +225,8 @@ func TestEvaluateField(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
capField CapabilityField
|
||||
config map[string]interface{}
|
||||
want interface{}
|
||||
config map[string]any
|
||||
want any
|
||||
}{
|
||||
{
|
||||
name: "no conditions returns default",
|
||||
@@ -235,7 +235,7 @@ func TestEvaluateField(t *testing.T) {
|
||||
Default: false,
|
||||
Conditions: nil,
|
||||
},
|
||||
config: map[string]interface{}{},
|
||||
config: map[string]any{},
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
@@ -245,7 +245,7 @@ func TestEvaluateField(t *testing.T) {
|
||||
Default: false,
|
||||
Conditions: []CapabilityCondition{},
|
||||
},
|
||||
config: map[string]interface{}{},
|
||||
config: map[string]any{},
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
@@ -260,7 +260,7 @@ func TestEvaluateField(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
config: map[string]interface{}{"SearchLocalModCacheLicenses": true},
|
||||
config: map[string]any{"SearchLocalModCacheLicenses": true},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
@@ -275,7 +275,7 @@ func TestEvaluateField(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
config: map[string]interface{}{"SearchLocalModCacheLicenses": false},
|
||||
config: map[string]any{"SearchLocalModCacheLicenses": false},
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
@@ -294,7 +294,7 @@ func TestEvaluateField(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
config: map[string]interface{}{
|
||||
config: map[string]any{
|
||||
"SearchLocalModCacheLicenses": true,
|
||||
"SearchRemoteLicenses": true,
|
||||
},
|
||||
@@ -316,7 +316,7 @@ func TestEvaluateField(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
config: map[string]interface{}{
|
||||
config: map[string]any{
|
||||
"SearchLocalModCacheLicenses": false,
|
||||
"SearchRemoteLicenses": true,
|
||||
},
|
||||
@@ -338,7 +338,7 @@ func TestEvaluateField(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
config: map[string]interface{}{
|
||||
config: map[string]any{
|
||||
"SearchLocalModCacheLicenses": false,
|
||||
"SearchRemoteLicenses": false,
|
||||
},
|
||||
@@ -351,7 +351,7 @@ func TestEvaluateField(t *testing.T) {
|
||||
Default: []string{"direct", "indirect"},
|
||||
Conditions: nil,
|
||||
},
|
||||
config: map[string]interface{}{},
|
||||
config: map[string]any{},
|
||||
want: []string{"direct", "indirect"},
|
||||
},
|
||||
{
|
||||
@@ -369,7 +369,7 @@ func TestEvaluateField(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
config: map[string]interface{}{
|
||||
config: map[string]any{
|
||||
"EnableFeatureA": true,
|
||||
"EnableFeatureB": true,
|
||||
},
|
||||
@@ -390,7 +390,7 @@ func TestEvaluateField(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
config: map[string]interface{}{
|
||||
config: map[string]any{
|
||||
"EnableFeatureA": true,
|
||||
"EnableFeatureB": false,
|
||||
},
|
||||
@@ -412,14 +412,14 @@ func TestEvaluateCapabilities(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
caps CapabilitySet
|
||||
config map[string]interface{}
|
||||
want map[string]interface{}
|
||||
config map[string]any
|
||||
want map[string]any
|
||||
}{
|
||||
{
|
||||
name: "empty capability set",
|
||||
caps: CapabilitySet{},
|
||||
config: map[string]interface{}{},
|
||||
want: map[string]interface{}{},
|
||||
config: map[string]any{},
|
||||
want: map[string]any{},
|
||||
},
|
||||
{
|
||||
name: "single capability no conditions",
|
||||
@@ -429,8 +429,8 @@ func TestEvaluateCapabilities(t *testing.T) {
|
||||
Default: false,
|
||||
},
|
||||
},
|
||||
config: map[string]interface{}{},
|
||||
want: map[string]interface{}{
|
||||
config: map[string]any{},
|
||||
want: map[string]any{
|
||||
"license": false,
|
||||
},
|
||||
},
|
||||
@@ -448,8 +448,8 @@ func TestEvaluateCapabilities(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
config: map[string]interface{}{"SearchLocalModCacheLicenses": true},
|
||||
want: map[string]interface{}{
|
||||
config: map[string]any{"SearchLocalModCacheLicenses": true},
|
||||
want: map[string]any{
|
||||
"license": true,
|
||||
},
|
||||
},
|
||||
@@ -475,8 +475,8 @@ func TestEvaluateCapabilities(t *testing.T) {
|
||||
Default: "flat",
|
||||
},
|
||||
},
|
||||
config: map[string]interface{}{"SearchLocalModCacheLicenses": true},
|
||||
want: map[string]interface{}{
|
||||
config: map[string]any{"SearchLocalModCacheLicenses": true},
|
||||
want: map[string]any{
|
||||
"license": true,
|
||||
"dependency.depth": []string{"direct", "indirect"},
|
||||
"dependency.edges": "flat",
|
||||
@@ -512,11 +512,11 @@ func TestEvaluateCapabilities(t *testing.T) {
|
||||
Default: false,
|
||||
},
|
||||
},
|
||||
config: map[string]interface{}{
|
||||
config: map[string]any{
|
||||
"SearchLocalModCacheLicenses": false,
|
||||
"SearchRemoteLicenses": true,
|
||||
},
|
||||
want: map[string]interface{}{
|
||||
want: map[string]any{
|
||||
"license": true,
|
||||
"dependency.depth": []string{"direct", "indirect"},
|
||||
"dependency.edges": "flat",
|
||||
@@ -526,10 +526,10 @@ func TestEvaluateCapabilities(t *testing.T) {
|
||||
{
|
||||
name: "nil capability set",
|
||||
caps: nil,
|
||||
config: map[string]interface{}{
|
||||
config: map[string]any{
|
||||
"anything": true,
|
||||
},
|
||||
want: map[string]interface{}{},
|
||||
want: map[string]any{},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -15,9 +15,9 @@ import (
|
||||
|
||||
// AppConfigField represents an application-level configuration field for catalogers
|
||||
type AppConfigField struct {
|
||||
Key string // e.g., "golang.search-local-mod-cache-licenses"
|
||||
Description string // extracted from DescribeFields() method
|
||||
DefaultValue interface{} // extracted from Default*() functions
|
||||
Key string // e.g., "golang.search-local-mod-cache-licenses"
|
||||
Description string // extracted from DescribeFields() method
|
||||
DefaultValue any // extracted from Default*() functions
|
||||
}
|
||||
|
||||
// extractEcosystemConfigFieldsFromCatalog parses catalog.go and extracts the ecosystem-specific
|
||||
@@ -390,7 +390,7 @@ func extractDescriptionsFromDescribeFields(f *ast.File) map[string]string {
|
||||
}
|
||||
|
||||
// extractNestedAppConfigs handles nested config structs like golang.MainModuleVersion
|
||||
func extractNestedAppConfigs(f *ast.File, parentKey, parentFieldName string, fieldType ast.Expr, descriptions map[string]string, defaults map[string]interface{}) []AppConfigField {
|
||||
func extractNestedAppConfigs(f *ast.File, parentKey, parentFieldName string, fieldType ast.Expr, descriptions map[string]string, defaults map[string]any) []AppConfigField {
|
||||
var configs []AppConfigField
|
||||
|
||||
// find the nested struct type
|
||||
@@ -449,8 +449,8 @@ func extractNestedAppConfigs(f *ast.File, parentKey, parentFieldName string, fie
|
||||
description := descriptions[nestedPath]
|
||||
|
||||
// try to get default value from nested defaults
|
||||
var defaultValue interface{}
|
||||
if nestedDefaults, ok := defaults[parentFieldName].(map[string]interface{}); ok {
|
||||
var defaultValue any
|
||||
if nestedDefaults, ok := defaults[parentFieldName].(map[string]any); ok {
|
||||
defaultValue = nestedDefaults[fieldName]
|
||||
}
|
||||
|
||||
@@ -465,8 +465,8 @@ func extractNestedAppConfigs(f *ast.File, parentKey, parentFieldName string, fie
|
||||
}
|
||||
|
||||
// extractAppDefaultValues extracts default values from the default*Config function
|
||||
func extractAppDefaultValues(f *ast.File) map[string]interface{} {
|
||||
defaults := make(map[string]interface{})
|
||||
func extractAppDefaultValues(f *ast.File) map[string]any {
|
||||
defaults := make(map[string]any)
|
||||
|
||||
for _, decl := range f.Decls {
|
||||
funcDecl, ok := decl.(*ast.FuncDecl)
|
||||
@@ -518,7 +518,7 @@ func extractAppDefaultValues(f *ast.File) map[string]interface{} {
|
||||
}
|
||||
|
||||
// extractAppValue extracts a Go value from an AST expression
|
||||
func extractAppValue(expr ast.Expr) interface{} {
|
||||
func extractAppValue(expr ast.Expr) any {
|
||||
switch v := expr.(type) {
|
||||
case *ast.BasicLit:
|
||||
// string, int, bool literals
|
||||
@@ -543,7 +543,7 @@ func extractAppValue(expr ast.Expr) interface{} {
|
||||
}
|
||||
case *ast.CompositeLit:
|
||||
// nested struct literal
|
||||
nested := make(map[string]interface{})
|
||||
nested := make(map[string]any)
|
||||
for _, elt := range v.Elts {
|
||||
kvExpr, ok := elt.(*ast.KeyValueExpr)
|
||||
if !ok {
|
||||
|
||||
@@ -340,7 +340,7 @@ func TestExtractAppValue(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
src string
|
||||
want interface{}
|
||||
want any
|
||||
}{
|
||||
{
|
||||
name: "string literal",
|
||||
@@ -406,7 +406,7 @@ func TestExtractAppValue_NestedStruct(t *testing.T) {
|
||||
got := extractAppValue(compositeLit)
|
||||
|
||||
// verify it's a map with the expected values
|
||||
gotMap, ok := got.(map[string]interface{})
|
||||
gotMap, ok := got.(map[string]any)
|
||||
require.True(t, ok)
|
||||
require.Equal(t, "value", gotMap["Field1"])
|
||||
require.Equal(t, true, gotMap["Field2"])
|
||||
|
||||
@@ -567,8 +567,8 @@ func resolveImportedConstant(pkgName, constName string, ctx *parseContext) strin
|
||||
// resolveImportPath converts an import path to a file system path
|
||||
func resolveImportPath(importPath, repoRoot string) string {
|
||||
// for github.com/anchore/syft/... imports, convert to repo-relative path
|
||||
if strings.HasPrefix(importPath, "github.com/anchore/syft/") {
|
||||
relPath := strings.TrimPrefix(importPath, "github.com/anchore/syft/")
|
||||
if after, ok := strings.CutPrefix(importPath, "github.com/anchore/syft/"); ok {
|
||||
relPath := after
|
||||
return filepath.Join(repoRoot, relPath)
|
||||
}
|
||||
|
||||
|
||||
@@ -214,7 +214,7 @@ func mapCatalogerToEcosystem(cat capabilities.CatalogerEntry) string {
|
||||
}
|
||||
|
||||
// updateNodeTreeEcosystem updates an existing ecosystem YAML node tree
|
||||
func updateNodeTreeEcosystem(rootNode *yaml.Node, doc interface{}) error {
|
||||
func updateNodeTreeEcosystem(rootNode *yaml.Node, doc any) error {
|
||||
var newNode yaml.Node
|
||||
if err := newNode.Encode(doc); err != nil {
|
||||
return err
|
||||
@@ -242,7 +242,7 @@ func updateNodeTreeEcosystem(rootNode *yaml.Node, doc interface{}) error {
|
||||
}
|
||||
|
||||
// updateNodeTreeAppConfig updates appconfig YAML node tree
|
||||
func updateNodeTreeAppConfig(rootNode *yaml.Node, doc interface{}) error {
|
||||
func updateNodeTreeAppConfig(rootNode *yaml.Node, doc any) error {
|
||||
return updateNodeTreeEcosystem(rootNode, doc)
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ const requireParserObservations = false
|
||||
|
||||
// metadataTypeCoverageExceptions lists metadata types that are allowed to not be represented in any cataloger
|
||||
var metadataTypeCoverageExceptions = strset.New(
|
||||
reflect.TypeOf(pkg.MicrosoftKbPatch{}).Name(),
|
||||
reflect.TypeFor[pkg.MicrosoftKbPatch]().Name(),
|
||||
)
|
||||
|
||||
// packageTypeCoverageExceptions lists package types that are allowed to not be represented in any cataloger
|
||||
@@ -408,7 +408,7 @@ func TestCapabilityValueTypes(t *testing.T) {
|
||||
}
|
||||
|
||||
// validateCapabilityValueType checks if a value matches the expected type for a capability field
|
||||
func validateCapabilityValueType(fieldPath string, value interface{}) error {
|
||||
func validateCapabilityValueType(fieldPath string, value any) error {
|
||||
if value == nil {
|
||||
return nil // nil is acceptable
|
||||
}
|
||||
@@ -428,7 +428,7 @@ func validateCapabilityValueType(fieldPath string, value interface{}) error {
|
||||
switch v := value.(type) {
|
||||
case []string:
|
||||
// ok
|
||||
case []interface{}:
|
||||
case []any:
|
||||
// check each element is a string
|
||||
for i, elem := range v {
|
||||
if _, ok := elem.(string); !ok {
|
||||
@@ -829,7 +829,6 @@ func TestCapabilityEvidenceFieldReferences(t *testing.T) {
|
||||
|
||||
// validate each evidence reference
|
||||
for _, ref := range allReferences {
|
||||
ref := ref // capture for subtest
|
||||
|
||||
// create test name
|
||||
testName := ref.catalogerName
|
||||
@@ -989,7 +988,6 @@ func validateCapabilitiesFilled(t *testing.T, catalogers []capabilities.Cataloge
|
||||
checkCompletenessTestsEnabled(t)
|
||||
|
||||
for _, c := range catalogers {
|
||||
c := c // capture loop variable for subtest
|
||||
|
||||
t.Run(c.Name, func(t *testing.T) {
|
||||
if c.Type == "generic" {
|
||||
@@ -997,7 +995,6 @@ func validateCapabilitiesFilled(t *testing.T, catalogers []capabilities.Cataloge
|
||||
require.NotEmpty(t, c.Parsers, "generic cataloger must have at least one parser")
|
||||
|
||||
for _, p := range c.Parsers {
|
||||
p := p // capture loop variable for subtest
|
||||
|
||||
t.Run(p.ParserFunction, func(t *testing.T) {
|
||||
require.NotEmpty(t, p.Capabilities, "parser must have at least one capability field defined")
|
||||
@@ -1120,7 +1117,6 @@ func TestCatalogerStructure(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
for _, c := range catalogerEntries {
|
||||
c := c // capture loop variable for subtest
|
||||
|
||||
t.Run(c.Name, func(t *testing.T) {
|
||||
// ecosystem must always be set (it's MANUAL)
|
||||
|
||||
Reference in New Issue
Block a user