From 2297c4f9b91189fa5902fae4b9f4051eec9eacf2 Mon Sep 17 00:00:00 2001 From: Kudryavcev Nikolay Date: Thu, 16 Oct 2025 00:15:34 +0300 Subject: [PATCH 1/3] remove duplicate providers if the DefaultImagePullSource parameter is set Signed-off-by: Kudryavcev Nikolay --- syft/get_source.go | 30 +++++++++++++++++++++++++++++- syft/get_source_config.go | 25 ------------------------- syft/get_source_test.go | 30 ++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 26 deletions(-) diff --git a/syft/get_source.go b/syft/get_source.go index e70f4cfe5a3..f94705eeead 100644 --- a/syft/get_source.go +++ b/syft/get_source.go @@ -7,7 +7,9 @@ import ( "os" "strings" + "github.com/anchore/go-collections" "github.com/anchore/syft/syft/source" + "github.com/anchore/syft/syft/source/sourceproviders" ) // GetSource uses all of Syft's known source providers to attempt to resolve the user input to a usable source.Source @@ -16,7 +18,7 @@ func GetSource(ctx context.Context, userInput string, cfg *GetSourceConfig) (sou cfg = DefaultGetSourceConfig() } - providers, err := cfg.getProviders(userInput) + providers, err := getProviders(userInput, cfg) if err != nil { return nil, err } @@ -53,6 +55,32 @@ func GetSource(ctx context.Context, userInput string, cfg *GetSourceConfig) (sou return nil, sourceError(userInput, errs...) } +func getProviders(userInput string, cfg *GetSourceConfig) ([]source.Provider, error) { + allSourceProviders := sourceproviders.All(userInput, cfg.SourceProviderConfig) + providers := collections.TaggedValueSet[source.Provider]{}.Join(allSourceProviders...) + + //if the "default image pull source" is set, we move this as the first pull source + if cfg.DefaultImagePullSource != "" { + base := providers.Remove(sourceproviders.PullTag) + pull := providers.Select(sourceproviders.PullTag) + def := pull.Select(cfg.DefaultImagePullSource) + if len(def) == 0 { + return nil, fmt.Errorf("invalid DefaultImagePullSource: %s; available values are: %v", cfg.DefaultImagePullSource, pull.Tags()) + } + + pullWithoutDef := pull.Remove(cfg.DefaultImagePullSource) + providers = base.Join(def...).Join(pullWithoutDef...) + } + + // narrow the sources to those explicitly requested generally by a user + if len(cfg.Sources) > 0 { + // select the explicitly provided sources, in order + providers = providers.Select(cfg.Sources...) + } + + return providers.Values(), nil +} + func validateSourcePlatform(src source.Source, cfg *GetSourceConfig) error { if src == nil { return nil diff --git a/syft/get_source_config.go b/syft/get_source_config.go index 7a163f1d1b6..83afd6703e6 100644 --- a/syft/get_source_config.go +++ b/syft/get_source_config.go @@ -2,9 +2,7 @@ package syft import ( "crypto" - "fmt" - "github.com/anchore/go-collections" "github.com/anchore/stereoscope/pkg/image" "github.com/anchore/syft/syft/source" "github.com/anchore/syft/syft/source/sourceproviders" @@ -61,29 +59,6 @@ func (c *GetSourceConfig) WithDefaultImagePullSource(defaultImagePullSource stri return c } -func (c *GetSourceConfig) getProviders(userInput string) ([]source.Provider, error) { - providers := collections.TaggedValueSet[source.Provider]{}.Join(sourceproviders.All(userInput, c.SourceProviderConfig)...) - - // if the "default image pull source" is set, we move this as the first pull source - if c.DefaultImagePullSource != "" { - base := providers.Remove(sourceproviders.PullTag) - pull := providers.Select(sourceproviders.PullTag) - def := pull.Select(c.DefaultImagePullSource) - if len(def) == 0 { - return nil, fmt.Errorf("invalid DefaultImagePullSource: %s; available values are: %v", c.DefaultImagePullSource, pull.Tags()) - } - providers = base.Join(def...).Join(pull...) - } - - // narrow the sources to those explicitly requested generally by a user - if len(c.Sources) > 0 { - // select the explicitly provided sources, in order - providers = providers.Select(c.Sources...) - } - - return providers.Values(), nil -} - func DefaultGetSourceConfig() *GetSourceConfig { return &GetSourceConfig{ SourceProviderConfig: sourceproviders.DefaultConfig(), diff --git a/syft/get_source_test.go b/syft/get_source_test.go index 241854c83cd..b0e780be2fc 100644 --- a/syft/get_source_test.go +++ b/syft/get_source_test.go @@ -3,6 +3,7 @@ package syft import ( "testing" + "github.com/anchore/stereoscope" "github.com/stretchr/testify/require" "github.com/anchore/stereoscope/pkg/image" @@ -20,6 +21,35 @@ func (s mockSource) Describe() source.Description { return s.desc } +func TestGetProviders_DefaultImagePullSource(t *testing.T) { + userInput := "" + cfg := &GetSourceConfig{DefaultImagePullSource: stereoscope.RegistryTag} + allSourceProviders := sourceproviders.All(userInput, cfg.SourceProviderConfig) + + providers, err := getProviders(userInput, cfg) + if err != nil { + t.Errorf("Expected no error for DefaultImagePullSource parameter, got: %v", err) + } + + if len(providers) != len(allSourceProviders) { + t.Errorf("Expected %d providers, got %d", len(allSourceProviders), len(providers)) + } +} + +func TestGetProviders_Sources(t *testing.T) { + userInput := "" + cfg := &GetSourceConfig{Sources: []string{stereoscope.RegistryTag}} + + providers, err := getProviders(userInput, cfg) + if err != nil { + t.Errorf("Expected no error for Sources parameter, got: %v", err) + } + + if len(providers) != 1 { + t.Errorf("Expected 1 providers, got %d", len(providers)) + } +} + func TestValidateSourcePlatform_NilSource(t *testing.T) { cfg := &GetSourceConfig{ SourceProviderConfig: &sourceproviders.Config{ From 4735e8210ce4b96c45f234c55e18209879969821 Mon Sep 17 00:00:00 2001 From: Kudryavcev Nikolay Date: Thu, 16 Oct 2025 00:50:42 +0300 Subject: [PATCH 2/3] fix comment formatting Signed-off-by: Kudryavcev Nikolay --- syft/get_source.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/syft/get_source.go b/syft/get_source.go index f94705eeead..a076ff9f516 100644 --- a/syft/get_source.go +++ b/syft/get_source.go @@ -59,7 +59,7 @@ func getProviders(userInput string, cfg *GetSourceConfig) ([]source.Provider, er allSourceProviders := sourceproviders.All(userInput, cfg.SourceProviderConfig) providers := collections.TaggedValueSet[source.Provider]{}.Join(allSourceProviders...) - //if the "default image pull source" is set, we move this as the first pull source + // if the "default image pull source" is set, we move this as the first pull source if cfg.DefaultImagePullSource != "" { base := providers.Remove(sourceproviders.PullTag) pull := providers.Select(sourceproviders.PullTag) From b8a5225f84335de0e57e8bf02ec6b041977c05f7 Mon Sep 17 00:00:00 2001 From: Kudryavcev Nikolay Date: Thu, 16 Oct 2025 22:58:34 +0300 Subject: [PATCH 3/3] chore(deps): bump github.com/anchore/go-collections and rollback getProviders Signed-off-by: Kudryavcev Nikolay --- go.mod | 2 +- go.sum | 4 ++-- syft/get_source.go | 30 +-------------------------- syft/get_source_config.go | 25 +++++++++++++++++++++++ syft/get_source_config_test.go | 37 ++++++++++++++++++++++++++++++++++ syft/get_source_test.go | 30 --------------------------- 6 files changed, 66 insertions(+), 62 deletions(-) create mode 100644 syft/get_source_config_test.go diff --git a/go.mod b/go.mod index cd7f8feee75..b4dda9cc4c1 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/anchore/bubbly v0.0.0-20231115134915-def0aba654a9 github.com/anchore/clio v0.0.0-20250319180342-2cfe4b0cb716 github.com/anchore/fangs v0.0.0-20250319222917-446a1e748ec2 - github.com/anchore/go-collections v0.0.0-20240216171411-9321230ce537 + github.com/anchore/go-collections v0.0.0-20251016125210-a3c352120e8c github.com/anchore/go-homedir v0.0.0-20250319154043-c29668562e4d github.com/anchore/go-logger v0.0.0-20250318195838-07ae343dd722 github.com/anchore/go-macholibre v0.0.0-20220308212642-53e6d0aaf6fb diff --git a/go.sum b/go.sum index 82fb633fe1c..0b94185963d 100644 --- a/go.sum +++ b/go.sum @@ -116,8 +116,8 @@ github.com/anchore/clio v0.0.0-20250319180342-2cfe4b0cb716 h1:2sIdYJlQESEnyk3Y0W github.com/anchore/clio v0.0.0-20250319180342-2cfe4b0cb716/go.mod h1:Utb9i4kwiCWvqAIxZaJeMIXFO9uOgQXlvH2BfbfO/zI= github.com/anchore/fangs v0.0.0-20250319222917-446a1e748ec2 h1:GC2QaO0YsmjpsZ4rtVKv9DnproIxqqn+qkskpc+i8MA= github.com/anchore/fangs v0.0.0-20250319222917-446a1e748ec2/go.mod h1:XUbUECwVKuD3qYRUj+QZIOHjyyXua2gFmVjKA40iHXA= -github.com/anchore/go-collections v0.0.0-20240216171411-9321230ce537 h1:GjNGuwK5jWjJMyVppBjYS54eOiiSNv4Ba869k4wh72Q= -github.com/anchore/go-collections v0.0.0-20240216171411-9321230ce537/go.mod h1:1aiktV46ATCkuVg0O573ZrH56BUawTECPETbZyBcqT8= +github.com/anchore/go-collections v0.0.0-20251016125210-a3c352120e8c h1:eoJXyC0n7DZ4YvySG/ETdYkTar2Due7eH+UmLK6FbrA= +github.com/anchore/go-collections v0.0.0-20251016125210-a3c352120e8c/go.mod h1:1aiktV46ATCkuVg0O573ZrH56BUawTECPETbZyBcqT8= github.com/anchore/go-homedir v0.0.0-20250319154043-c29668562e4d h1:gT69osH9AsdpOfqxbRwtxcNnSZ1zg4aKy2BevO3ZBdc= github.com/anchore/go-homedir v0.0.0-20250319154043-c29668562e4d/go.mod h1:PhSnuFYknwPZkOWKB1jXBNToChBA+l0FjwOxtViIc50= github.com/anchore/go-logger v0.0.0-20250318195838-07ae343dd722 h1:2SqmFgE7h+Ql4VyBzhjLkRF/3gDrcpUBj8LjvvO6OOM= diff --git a/syft/get_source.go b/syft/get_source.go index a076ff9f516..e70f4cfe5a3 100644 --- a/syft/get_source.go +++ b/syft/get_source.go @@ -7,9 +7,7 @@ import ( "os" "strings" - "github.com/anchore/go-collections" "github.com/anchore/syft/syft/source" - "github.com/anchore/syft/syft/source/sourceproviders" ) // GetSource uses all of Syft's known source providers to attempt to resolve the user input to a usable source.Source @@ -18,7 +16,7 @@ func GetSource(ctx context.Context, userInput string, cfg *GetSourceConfig) (sou cfg = DefaultGetSourceConfig() } - providers, err := getProviders(userInput, cfg) + providers, err := cfg.getProviders(userInput) if err != nil { return nil, err } @@ -55,32 +53,6 @@ func GetSource(ctx context.Context, userInput string, cfg *GetSourceConfig) (sou return nil, sourceError(userInput, errs...) } -func getProviders(userInput string, cfg *GetSourceConfig) ([]source.Provider, error) { - allSourceProviders := sourceproviders.All(userInput, cfg.SourceProviderConfig) - providers := collections.TaggedValueSet[source.Provider]{}.Join(allSourceProviders...) - - // if the "default image pull source" is set, we move this as the first pull source - if cfg.DefaultImagePullSource != "" { - base := providers.Remove(sourceproviders.PullTag) - pull := providers.Select(sourceproviders.PullTag) - def := pull.Select(cfg.DefaultImagePullSource) - if len(def) == 0 { - return nil, fmt.Errorf("invalid DefaultImagePullSource: %s; available values are: %v", cfg.DefaultImagePullSource, pull.Tags()) - } - - pullWithoutDef := pull.Remove(cfg.DefaultImagePullSource) - providers = base.Join(def...).Join(pullWithoutDef...) - } - - // narrow the sources to those explicitly requested generally by a user - if len(cfg.Sources) > 0 { - // select the explicitly provided sources, in order - providers = providers.Select(cfg.Sources...) - } - - return providers.Values(), nil -} - func validateSourcePlatform(src source.Source, cfg *GetSourceConfig) error { if src == nil { return nil diff --git a/syft/get_source_config.go b/syft/get_source_config.go index 83afd6703e6..7a163f1d1b6 100644 --- a/syft/get_source_config.go +++ b/syft/get_source_config.go @@ -2,7 +2,9 @@ package syft import ( "crypto" + "fmt" + "github.com/anchore/go-collections" "github.com/anchore/stereoscope/pkg/image" "github.com/anchore/syft/syft/source" "github.com/anchore/syft/syft/source/sourceproviders" @@ -59,6 +61,29 @@ func (c *GetSourceConfig) WithDefaultImagePullSource(defaultImagePullSource stri return c } +func (c *GetSourceConfig) getProviders(userInput string) ([]source.Provider, error) { + providers := collections.TaggedValueSet[source.Provider]{}.Join(sourceproviders.All(userInput, c.SourceProviderConfig)...) + + // if the "default image pull source" is set, we move this as the first pull source + if c.DefaultImagePullSource != "" { + base := providers.Remove(sourceproviders.PullTag) + pull := providers.Select(sourceproviders.PullTag) + def := pull.Select(c.DefaultImagePullSource) + if len(def) == 0 { + return nil, fmt.Errorf("invalid DefaultImagePullSource: %s; available values are: %v", c.DefaultImagePullSource, pull.Tags()) + } + providers = base.Join(def...).Join(pull...) + } + + // narrow the sources to those explicitly requested generally by a user + if len(c.Sources) > 0 { + // select the explicitly provided sources, in order + providers = providers.Select(c.Sources...) + } + + return providers.Values(), nil +} + func DefaultGetSourceConfig() *GetSourceConfig { return &GetSourceConfig{ SourceProviderConfig: sourceproviders.DefaultConfig(), diff --git a/syft/get_source_config_test.go b/syft/get_source_config_test.go new file mode 100644 index 00000000000..9d0ad877472 --- /dev/null +++ b/syft/get_source_config_test.go @@ -0,0 +1,37 @@ +package syft + +import ( + "testing" + + "github.com/anchore/stereoscope" + "github.com/anchore/syft/syft/source/sourceproviders" +) + +func TestGetProviders_DefaultImagePullSource(t *testing.T) { + userInput := "" + cfg := &GetSourceConfig{DefaultImagePullSource: stereoscope.RegistryTag} + allSourceProviders := sourceproviders.All(userInput, cfg.SourceProviderConfig) + + providers, err := cfg.getProviders(userInput) + if err != nil { + t.Errorf("Expected no error for DefaultImagePullSource parameter, got: %v", err) + } + + if len(providers) != len(allSourceProviders) { + t.Errorf("Expected %d providers, got %d", len(allSourceProviders), len(providers)) + } +} + +func TestGetProviders_Sources(t *testing.T) { + userInput := "" + cfg := &GetSourceConfig{Sources: []string{stereoscope.RegistryTag}} + + providers, err := cfg.getProviders(userInput) + if err != nil { + t.Errorf("Expected no error for Sources parameter, got: %v", err) + } + + if len(providers) != 1 { + t.Errorf("Expected 1 providers, got %d", len(providers)) + } +} diff --git a/syft/get_source_test.go b/syft/get_source_test.go index b0e780be2fc..241854c83cd 100644 --- a/syft/get_source_test.go +++ b/syft/get_source_test.go @@ -3,7 +3,6 @@ package syft import ( "testing" - "github.com/anchore/stereoscope" "github.com/stretchr/testify/require" "github.com/anchore/stereoscope/pkg/image" @@ -21,35 +20,6 @@ func (s mockSource) Describe() source.Description { return s.desc } -func TestGetProviders_DefaultImagePullSource(t *testing.T) { - userInput := "" - cfg := &GetSourceConfig{DefaultImagePullSource: stereoscope.RegistryTag} - allSourceProviders := sourceproviders.All(userInput, cfg.SourceProviderConfig) - - providers, err := getProviders(userInput, cfg) - if err != nil { - t.Errorf("Expected no error for DefaultImagePullSource parameter, got: %v", err) - } - - if len(providers) != len(allSourceProviders) { - t.Errorf("Expected %d providers, got %d", len(allSourceProviders), len(providers)) - } -} - -func TestGetProviders_Sources(t *testing.T) { - userInput := "" - cfg := &GetSourceConfig{Sources: []string{stereoscope.RegistryTag}} - - providers, err := getProviders(userInput, cfg) - if err != nil { - t.Errorf("Expected no error for Sources parameter, got: %v", err) - } - - if len(providers) != 1 { - t.Errorf("Expected 1 providers, got %d", len(providers)) - } -} - func TestValidateSourcePlatform_NilSource(t *testing.T) { cfg := &GetSourceConfig{ SourceProviderConfig: &sourceproviders.Config{