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  }