github.com/Racer159/jackal@v0.32.7-0.20240401174413-0bd2339e4f2e/src/pkg/packager/sources/new.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // SPDX-FileCopyrightText: 2021-Present The Jackal Authors 3 4 // Package sources contains core implementations of the PackageSource interface. 5 package sources 6 7 import ( 8 "fmt" 9 "net/url" 10 "strings" 11 12 "github.com/Racer159/jackal/src/config" 13 "github.com/Racer159/jackal/src/pkg/layout" 14 "github.com/Racer159/jackal/src/pkg/message" 15 "github.com/Racer159/jackal/src/pkg/packager/filters" 16 "github.com/Racer159/jackal/src/pkg/zoci" 17 "github.com/Racer159/jackal/src/types" 18 "github.com/defenseunicorns/pkg/helpers" 19 "github.com/defenseunicorns/pkg/oci" 20 ) 21 22 // PackageSource is an interface for package sources. 23 // 24 // While this interface defines three functions, LoadPackage, LoadPackageMetadata, and Collect; only one of them should be used within a packager function. 25 // 26 // These functions currently do not promise repeatability due to the side effect nature of loading a package. 27 // 28 // Signature and integrity validation is up to the implementation of the package source. 29 // 30 // `sources.ValidatePackageSignature` and `sources.ValidatePackageIntegrity` can be leveraged for this purpose. 31 type PackageSource interface { 32 // LoadPackage loads a package from a source. 33 LoadPackage(dst *layout.PackagePaths, filter filters.ComponentFilterStrategy, unarchiveAll bool) (pkg types.JackalPackage, warnings []string, err error) 34 35 // LoadPackageMetadata loads a package's metadata from a source. 36 LoadPackageMetadata(dst *layout.PackagePaths, wantSBOM bool, skipValidation bool) (pkg types.JackalPackage, warnings []string, err error) 37 38 // Collect relocates a package from its source to a tarball in a given destination directory. 39 Collect(destinationDirectory string) (tarball string, err error) 40 } 41 42 // Identify returns the type of package source based on the provided package source string. 43 func Identify(pkgSrc string) string { 44 if helpers.IsURL(pkgSrc) { 45 parsed, _ := url.Parse(pkgSrc) 46 return parsed.Scheme 47 } 48 49 if strings.Contains(pkgSrc, ".part000") { 50 return "split" 51 } 52 53 if IsValidFileExtension(pkgSrc) { 54 return "tarball" 55 } 56 57 return "" 58 } 59 60 // New returns a new PackageSource based on the provided package options. 61 func New(pkgOpts *types.JackalPackageOptions) (PackageSource, error) { 62 var source PackageSource 63 64 pkgSrc := pkgOpts.PackageSource 65 66 switch Identify(pkgSrc) { 67 case "oci": 68 if pkgOpts.Shasum != "" { 69 pkgSrc = fmt.Sprintf("%s@sha256:%s", pkgSrc, pkgOpts.Shasum) 70 } 71 arch := config.GetArch() 72 remote, err := zoci.NewRemote(pkgSrc, oci.PlatformForArch(arch)) 73 if err != nil { 74 return nil, err 75 } 76 source = &OCISource{JackalPackageOptions: pkgOpts, Remote: remote} 77 case "tarball": 78 source = &TarballSource{pkgOpts} 79 case "http", "https", "sget": 80 source = &URLSource{pkgOpts} 81 case "split": 82 source = &SplitTarballSource{pkgOpts} 83 default: 84 return nil, fmt.Errorf("could not identify source type for %q", pkgSrc) 85 } 86 87 message.Debugf("Using %T for %q", source, pkgSrc) 88 89 return source, nil 90 }