syft/syft/get_source.go
Christopher Angelo Phillips 2c5e193f7a
feat: Add support for scanning GGUF models from OCI registries (#4335)
---------
Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
Co-authored-by: Alex Goodman <wagoodman@users.noreply.github.com>
2026-02-09 16:05:52 -05:00

90 lines
2.2 KiB
Go

package syft
import (
"context"
"errors"
"fmt"
"os"
"strings"
"github.com/anchore/syft/syft/source"
)
// GetSource uses all of Syft's known source providers to attempt to resolve the user input to a usable source.Source
func GetSource(ctx context.Context, userInput string, cfg *GetSourceConfig) (source.Source, error) {
if cfg == nil {
cfg = DefaultGetSourceConfig()
}
providers, err := cfg.getProviders(userInput)
if err != nil {
return nil, err
}
var errs []error
var fileNotFoundProviders []string
// call each source provider until we find a valid source
for _, p := range providers {
src, err := p.Provide(ctx)
if err != nil {
if errors.Is(err, os.ErrNotExist) {
fileNotFoundProviders = append(fileNotFoundProviders, p.Name())
} else {
errs = append(errs, fmt.Errorf("%s: %w", p.Name(), err))
}
}
if err := validateSourcePlatform(src, cfg); err != nil {
return nil, err
}
if src != nil {
return src, nil
}
}
if len(errs) == 0 {
return nil, fmt.Errorf("no source providers were able to resolve the input %q", userInput)
}
if len(fileNotFoundProviders) > 0 {
errs = append(errs, fmt.Errorf("additionally, the following providers failed with %w: %s", os.ErrNotExist, strings.Join(fileNotFoundProviders, ", ")))
}
return nil, sourceError(userInput, errs...)
}
func validateSourcePlatform(src source.Source, cfg *GetSourceConfig) error {
if src == nil {
return nil
}
if cfg == nil || cfg.SourceProviderConfig == nil || cfg.SourceProviderConfig.Platform == nil {
return nil
}
meta := src.Describe().Metadata
switch meta.(type) {
case *source.ImageMetadata, source.ImageMetadata:
return nil
case *source.OCIModelMetadata, source.OCIModelMetadata:
return nil
case *source.SnapMetadata, source.SnapMetadata:
return nil
default:
return fmt.Errorf("platform is not supported for this source type")
}
}
func sourceError(userInput string, errs ...error) error {
switch len(errs) {
case 0:
return nil
case 1:
return fmt.Errorf("an error occurred attempting to resolve '%s': %w", userInput, errs[0])
}
errorTexts := ""
for _, e := range errs {
errorTexts += fmt.Sprintf("\n - %s", e)
}
return fmt.Errorf("errors occurred attempting to resolve '%s':%s", userInput, errorTexts)
}