config: move symbol enum to cataloging pkg

Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com>
This commit is contained in:
Christopher Phillips 2026-07-01 02:11:44 -04:00
parent a1831ce3b4
commit 46f9974fec
No known key found for this signature in database
11 changed files with 87 additions and 71 deletions

View File

@ -5,6 +5,7 @@ import (
"strings"
"github.com/anchore/clio"
"github.com/anchore/syft/syft/cataloging"
"github.com/anchore/syft/syft/pkg/cataloger/golang"
)
@ -18,7 +19,7 @@ type golangConfig struct {
NoProxy string `json:"no-proxy" yaml:"no-proxy" mapstructure:"no-proxy"`
MainModuleVersion golangMainModuleVersionConfig `json:"main-module-version" yaml:"main-module-version" mapstructure:"main-module-version"`
UsePackagesLib *bool `json:"use-packages-lib" yaml:"use-packages-lib" mapstructure:"use-packages-lib"`
CaptureSymbols golang.SymbolScope `json:"capture-symbols" yaml:"capture-symbols" mapstructure:"capture-symbols"`
CaptureSymbols cataloging.SymbolScope `json:"capture-symbols" yaml:"capture-symbols" mapstructure:"capture-symbols"`
}
var _ interface {

View File

@ -5,30 +5,30 @@ import (
"github.com/stretchr/testify/assert"
"github.com/anchore/syft/syft/pkg/cataloger/golang"
"github.com/anchore/syft/syft/cataloging"
)
func Test_golangConfig_PostLoad(t *testing.T) {
tests := []struct {
name string
cfg golangConfig
expected golang.SymbolScope
expected cataloging.SymbolScope
wantErr assert.ErrorAssertionFunc
}{
{
name: "normalize all",
cfg: golangConfig{CaptureSymbols: "all"},
expected: golang.SymbolScopeAll,
expected: cataloging.SymbolScopeAll,
},
{
name: "normalize stdlib",
cfg: golangConfig{CaptureSymbols: "stdlib"},
expected: golang.SymbolScopeStdlib,
expected: cataloging.SymbolScopeStdlib,
},
{
name: "empty defaults to none",
cfg: golangConfig{CaptureSymbols: ""},
expected: golang.SymbolScopeNone,
expected: cataloging.SymbolScopeNone,
},
{
name: "error on invalid value",

View File

@ -10,6 +10,7 @@ const (
// 16.1.1 - correct elf package osCpe field according to the document of systemd (also add appCpe field)
// 16.1.2 - placeholder for 16.1.2 changelog
// 16.1.3 - add GGUFFileParts to GGUFFileHeader metadata
// 16.1.4 - add BunLockEntry metadata type for bun.lock support
// 16.1.5 - add DenoLockEntry and DenoRemoteLockEntry metadata types for deno.lock support
// 16.1.6 - add Dependencies to ElixirMixLockEntry metadata
// 16.1.7 - add AppleAppBundleEntry metadata type for the apple app bundle cataloger

View File

@ -1659,7 +1659,7 @@
"type": "string"
},
"type": "array",
"description": "Symbols are the fully qualified function symbols from this module that are compiled into the binary\n(e.g., \"github.com/foo/bar.(*Type).Method\"), extracted from the binary symbol table (pclntab).\nOnly captured when the golang cataloger is configured to capture symbols."
"description": "Symbols are the fully qualified function symbols from this module that are compiled into the binary\n(e.g., \"github.com/foo/bar.(*Type).Method\"), extracted from the binary symbol table (pclntab).\nPopulated only when the golang cataloger's capture-symbols scope covers this package: the \"all\" scope\npopulates every module package plus the synthetic stdlib package, while the \"stdlib\" scope populates\nonly the stdlib package."
}
},
"type": "object",

View File

@ -1659,7 +1659,7 @@
"type": "string"
},
"type": "array",
"description": "Symbols are the fully qualified function symbols from this module that are compiled into the binary\n(e.g., \"github.com/foo/bar.(*Type).Method\"), extracted from the binary symbol table (pclntab).\nOnly captured when the golang cataloger is configured to capture symbols."
"description": "Symbols are the fully qualified function symbols from this module that are compiled into the binary\n(e.g., \"github.com/foo/bar.(*Type).Method\"), extracted from the binary symbol table (pclntab).\nPopulated only when the golang cataloger's capture-symbols scope covers this package: the \"all\" scope\npopulates every module package plus the synthetic stdlib package, while the \"stdlib\" scope populates\nonly the stdlib package."
}
},
"type": "object",

View File

@ -0,0 +1,31 @@
package cataloging
import "strings"
// SymbolScope controls which packages get function symbols (from a binary's symbol table) attached to their metadata.
type SymbolScope string
const (
// SymbolScopeNone disables symbol capture entirely.
SymbolScopeNone SymbolScope = "none"
// SymbolScopeStdlib captures symbols only for the synthetic "stdlib" package, leaving module packages without symbols.
SymbolScopeStdlib SymbolScope = "stdlib"
// SymbolScopeAll captures symbols for all module packages as well as the synthetic "stdlib" package.
SymbolScopeAll SymbolScope = "all"
)
// Parse normalizes a SymbolScope, treating an empty (unset) value as SymbolScopeNone. It returns an empty
// SymbolScope to signal an unrecognized value, which callers validate against.
func (s SymbolScope) Parse() SymbolScope {
switch strings.ToLower(strings.TrimSpace(string(s))) {
case string(SymbolScopeAll):
return SymbolScopeAll
case string(SymbolScopeStdlib):
return SymbolScopeStdlib
case string(SymbolScopeNone), "":
return SymbolScopeNone
}
return ""
}

View File

@ -0,0 +1,30 @@
package cataloging
import (
"testing"
"github.com/stretchr/testify/assert"
)
func Test_SymbolScope_Parse(t *testing.T) {
tests := []struct {
input string
expected SymbolScope
}{
{"all", SymbolScopeAll},
{"ALL", SymbolScopeAll},
{" all ", SymbolScopeAll},
{"stdlib", SymbolScopeStdlib},
{"Stdlib", SymbolScopeStdlib},
{"none", SymbolScopeNone},
{"", SymbolScopeNone},
{"true", ""},
{"false", ""},
{"bogus", ""},
}
for _, test := range tests {
t.Run(test.input, func(t *testing.T) {
assert.Equal(t, test.expected, SymbolScope(test.input).Parse())
})
}
}

View File

@ -7,6 +7,7 @@ import (
"github.com/anchore/go-homedir"
"github.com/anchore/syft/internal/log"
"github.com/anchore/syft/syft/cataloging"
)
const (
@ -18,34 +19,6 @@ var (
directProxiesOnly = []string{directProxyOnly}
)
// SymbolScope controls which packages get function symbols (from the binary pclntab) attached to their metadata.
type SymbolScope string
const (
// SymbolScopeNone disables symbol capture entirely.
SymbolScopeNone SymbolScope = "none"
// SymbolScopeStdlib captures symbols only for the synthetic "stdlib" package, leaving module packages without symbols.
SymbolScopeStdlib SymbolScope = "stdlib"
// SymbolScopeAll captures symbols for all module packages as well as the synthetic "stdlib" package.
SymbolScopeAll SymbolScope = "all"
)
// Parse normalizes a SymbolScope, treating an empty (unset) value as SymbolScopeNone. It returns an empty
// SymbolScope to signal an unrecognized value, which callers validate against.
func (s SymbolScope) Parse() SymbolScope {
switch strings.ToLower(strings.TrimSpace(string(s))) {
case string(SymbolScopeAll):
return SymbolScopeAll
case string(SymbolScopeStdlib):
return SymbolScopeStdlib
case string(SymbolScopeNone), "":
return SymbolScopeNone
}
return ""
}
type CatalogerConfig struct {
// SearchLocalModCacheLicenses enables searching for go package licenses in the local GOPATH mod cache.
// app-config: golang.search-local-mod-cache-licenses
@ -80,7 +53,7 @@ type CatalogerConfig struct {
// CaptureSymbols controls extracting function symbols from the binary symbol table (pclntab). Valid values are
// "none" (disabled), "stdlib" (only the synthetic stdlib package), and "all" (all module packages plus stdlib).
// app-config: golang.capture-symbols
CaptureSymbols SymbolScope `yaml:"capture-symbols" json:"capture-symbols" mapstructure:"capture-symbols"`
CaptureSymbols cataloging.SymbolScope `yaml:"capture-symbols" json:"capture-symbols" mapstructure:"capture-symbols"`
// Whether to use the golang.org/x/tools/go/packages, which executes golang tooling found on the path in addition to potential network access
UsePackagesLib bool `json:"use-packages-lib" yaml:"use-packages-lib" mapstructure:"use-packages-lib"`
@ -109,7 +82,7 @@ func DefaultCatalogerConfig() CatalogerConfig {
UsePackagesLib: true,
MainModuleVersion: DefaultMainModuleVersionConfig(),
LocalModCacheDir: defaultGoModDir(),
CaptureSymbols: SymbolScopeNone,
CaptureSymbols: cataloging.SymbolScopeNone,
}
// first process the proxy settings
@ -218,7 +191,7 @@ func (g CatalogerConfig) WithMainModuleVersion(input MainModuleVersionConfig) Ca
return g
}
func (g CatalogerConfig) WithCaptureSymbols(input SymbolScope) CatalogerConfig {
func (g CatalogerConfig) WithCaptureSymbols(input cataloging.SymbolScope) CatalogerConfig {
g.CaptureSymbols = input
return g
}

View File

@ -7,6 +7,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/anchore/go-homedir"
"github.com/anchore/syft/syft/cataloging"
)
func Test_Config(t *testing.T) {
@ -58,7 +59,7 @@ func Test_Config(t *testing.T) {
NoProxy: []string{"my.private", "no.proxy"},
MainModuleVersion: DefaultMainModuleVersionConfig(),
UsePackagesLib: true,
CaptureSymbols: SymbolScopeNone,
CaptureSymbols: cataloging.SymbolScopeNone,
},
},
{
@ -87,7 +88,7 @@ func Test_Config(t *testing.T) {
NoProxy: []string{"alt.no.proxy"},
MainModuleVersion: DefaultMainModuleVersionConfig(),
UsePackagesLib: true,
CaptureSymbols: SymbolScopeNone,
CaptureSymbols: cataloging.SymbolScopeNone,
},
},
}
@ -114,29 +115,6 @@ func Test_Config(t *testing.T) {
}
}
func Test_SymbolScope_Parse(t *testing.T) {
tests := []struct {
input string
expected SymbolScope
}{
{"all", SymbolScopeAll},
{"ALL", SymbolScopeAll},
{" all ", SymbolScopeAll},
{"stdlib", SymbolScopeStdlib},
{"Stdlib", SymbolScopeStdlib},
{"none", SymbolScopeNone},
{"", SymbolScopeNone},
{"true", ""},
{"false", ""},
{"bogus", ""},
}
for _, test := range tests {
t.Run(test.input, func(t *testing.T) {
assert.Equal(t, test.expected, SymbolScope(test.input).Parse())
})
}
}
// restoreCache ensures cache settings are restored after test
func restoreCache(t testing.TB) {
t.Helper()

View File

@ -21,6 +21,7 @@ import (
"github.com/anchore/syft/internal"
"github.com/anchore/syft/internal/log"
"github.com/anchore/syft/syft/artifact"
"github.com/anchore/syft/syft/cataloging"
"github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/internal/unionreader"
"github.com/anchore/syft/syft/pkg"
@ -50,7 +51,7 @@ const devel = "(devel)"
type goBinaryCataloger struct {
licenseResolver goLicenseResolver
mainModuleVersion MainModuleVersionConfig
symbolScope SymbolScope
symbolScope cataloging.SymbolScope
// stdlibSymbols holds the standard-library function symbols discovered per binary (keyed by the
// binary's location), populated during parsing and consumed by stdlibProcessor when it builds the
@ -98,7 +99,7 @@ func (c *goBinaryCataloger) parseGoBinary(ctx context.Context, resolver file.Res
}
defer internal.CloseAndLogError(reader.ReadCloser, reader.RealPath)
mods, errs := scanFile(reader.Location, unionReader, c.symbolScope != SymbolScopeNone)
mods, errs := scanFile(reader.Location, unionReader, c.symbolScope != cataloging.SymbolScopeNone)
var rels []artifact.Relationship
for _, mod := range mods {
@ -161,7 +162,7 @@ func (c *goBinaryCataloger) buildGoPkgInfo(ctx context.Context, resolver file.Re
symbolsByModule, stdlibSymbols := moduleSymbols(mod.symbols, &mod.Main, mod.Deps)
c.recordStdlibSymbols(location.Coordinates, stdlibSymbols)
if c.symbolScope != SymbolScopeAll {
if c.symbolScope != cataloging.SymbolScopeAll {
// only the "all" scope attaches per-module symbols; for the "stdlib" scope we keep just the
// recorded stdlib symbols. nil map lookups below then yield nil symbol lists for each module.
symbolsByModule = nil

View File

@ -18,6 +18,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/anchore/syft/syft/cataloging"
"github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/internal/fileresolver"
"github.com/anchore/syft/syft/internal/unionreader"
@ -1437,7 +1438,7 @@ func Test_buildGoPkgInfo_symbolScope(t *testing.T) {
tests := []struct {
name string
scope SymbolScope
scope cataloging.SymbolScope
symbols []binarySymbol
wantMainSyms []string
wantDepSyms []string
@ -1445,18 +1446,18 @@ func Test_buildGoPkgInfo_symbolScope(t *testing.T) {
}{
{
name: "none captures nothing",
scope: SymbolScopeNone,
scope: cataloging.SymbolScopeNone,
symbols: nil,
},
{
name: "stdlib captures only the stdlib package",
scope: SymbolScopeStdlib,
scope: cataloging.SymbolScopeStdlib,
symbols: populatedSymbols,
wantStdlibSyms: []string{"net/http.(*Client).Do"},
},
{
name: "all captures module and stdlib packages",
scope: SymbolScopeAll,
scope: cataloging.SymbolScopeAll,
symbols: populatedSymbols,
wantMainSyms: []string{"main.main"},
wantDepSyms: []string{"github.com/foo/bar.Parse"},